def test_load_file(tmp_dir): """Test load file.""" json_file_path = pathlib.Path.joinpath(test_utils.JSON_TEST_DATA_PATH, 'sample-target-definition.json') yaml_file_path = pathlib.Path.joinpath(test_utils.YAML_TEST_DATA_PATH, 'good_target.yaml') assert fs.load_file(json_file_path) is not None assert fs.load_file(yaml_file_path) is not None try: sample_file_path = tmp_dir.joinpath('sample.txt') with open(sample_file_path, 'w'): fs.load_file(sample_file_path) except TrestleError: pass
def parse_file(file_name: str, model_name: str): """Load a model from the file. Argument: model_name: it should be of the form <module>.<class> <class> should be a Pydantic class that supports `parse_obj` method """ warnings.warn('trestle.parser functions are deprecated', DeprecationWarning) if file_name is None: raise TrestleError('file_name is required') data = fs.load_file(file_name) rkey = root_key(data) if model_name is None: model_name = to_full_model_name(rkey) return parse_dict(data[rkey], model_name)
def parse_file(file_name: pathlib.Path, model_name: Optional[str]) -> OscalBaseModel: """ Load an oscal file from the file system where the oscal model type is not known. Args: file_name: File path model_name: it should be of the form module.class which is derived from OscalBaseModel """ if file_name is None: raise TrestleError('file_name is required') data = fs.load_file(file_name) rkey = root_key(data) if model_name is None: model_name = to_full_model_name(rkey) return _parse_dict(data[rkey], model_name)
def _run(self, args: argparse.Namespace) -> int: """Top level import run command.""" log.set_log_level_from_args(args) logger.debug('Entering import run.') # 1. Validate input arguments are as expected. # This code block may never be reached as the argument is declared to be required. # 1.1 Check that input file given exists. input_file = pathlib.Path(args.file) if not input_file.exists(): logger.error(f'Input file {args.file} does not exist.') return 1 # 1.2 Bad working directory if not running from current working directory cwd = pathlib.Path.cwd().resolve() trestle_root = fs.get_trestle_project_root(cwd) if trestle_root is None: logger.error( f'Current working directory: {cwd} is not within a trestle project.' ) return 1 # 2. Importing a file that is already inside a trestle-initialized dir is bad trestle_root = trestle_root.resolve() try: input_file.absolute().relative_to(trestle_root) except ValueError: # An exception here is good: it means that the input file is not inside a trestle dir. pass else: logger.error( 'Input file cannot be from current trestle project. Use duplicate instead.' ) return 1 # 3. Work out typing information from input suffix. try: content_type = FileContentType.to_content_type(input_file.suffix) except TrestleError as err: logger.debug(f'FileContentType.to_content_type() failed: {err}') logger.error( f'Import failed, could not work out content type from file suffix: {err}' ) return 1 # 4. Load input and parse for model # 4.1 Load from file try: data = fs.load_file(input_file.absolute()) except JSONDecodeError as err: logger.debug(f'fs.load_file() failed: {err}') logger.error(f'Import failed, JSON error loading file: {err}') return 1 except TrestleError as err: logger.debug(f'fs.load_file() failed: {err}') logger.error(f'Import failed, error loading file: {err}') return 1 except PermissionError as err: logger.debug(f'fs.load_file() failed: {err}') logger.error( f'Import failed, access permission error loading file: {err}') return 1 # 4.2 root key check try: parent_alias = parser.root_key(data) except TrestleError as err: logger.debug(f'parser.root_key() failed: {err}') logger.error( f'Import failed, failed to parse input file for root key: {err}' ) return 1 # 4.3 parse the model parent_model_name = parser.to_full_model_name(parent_alias) try: parent_model = parser.parse_file(input_file.absolute(), parent_model_name) except TrestleError as err: logger.debug(f'parser.parse_file() failed: {err}') logger.error( f'Import failed, failed to parse valid contents of input file: {err}' ) return 1 # 5. Work out output directory and file plural_path: str plural_path = parent_alias # Cater to POAM if parent_alias[-1] != 's': plural_path = parent_alias + 's' desired_model_dir = trestle_root / plural_path # args.output is presumed to be assured as it is declared to be required if args.output: desired_model_path = desired_model_dir / args.output / ( parent_alias + input_file.suffix) if desired_model_path.exists(): logger.error( f'OSCAL file to be created here: {desired_model_path} exists.') logger.error('Aborting trestle import.') return 1 # 6. Prepare actions and plan top_element = Element(parent_model.oscal_read(input_file)) create_action = CreatePathAction(desired_model_path.absolute(), True) write_action = WriteFileAction(desired_model_path.absolute(), top_element, content_type) # create a plan to create the directory and imported file. import_plan = Plan() import_plan.add_action(create_action) import_plan.add_action(write_action) try: import_plan.simulate() except TrestleError as err: logger.debug(f'import_plan.simulate() failed: {err}') logger.error( f'Import failed, error in testing import operation: {err}') return 1 try: import_plan.execute() except TrestleError as err: logger.debug(f'import_plan.execute() failed: {err}') logger.error( f'Import failed, error in actual import operation: {err}') return 1 # 7. Leave the rest to trestle split return 0