def check_status(response: Response, project: Project, step: ProjectStep, force: bool = False) -> str: """ :param response: :param project: :param step: :param force: :return: """ path = step.source_path if step.is_muted: environ.log('[{}]: Muted (skipped)'.format(step.definition.name)) return SKIP_STATUS if not os.path.exists(path): response.fail(code='MISSING_SOURCE_FILE', message='Source file not found "{}"'.format(path), id=step.definition.name, path=path).console('[{id}]: Not found "{path}"'.format( id=step.definition.name, path=path)) return ERROR_STATUS if not force and not step.is_dirty(): environ.log('[{}]: Nothing to update'.format(step.definition.name)) return SKIP_STATUS return OK_STATUS
def toggle_muting(response: Response, project: Project, step_name: str, value: bool = None) -> Response: """ :param response: :param project: :param step_name: :param value: :return: """ index = project.index_of_step(step_name) if index is None: return response.fail( code='NO_SUCH_STEP', message='No step found with name: "{}"'.format(step_name)).kernel( name=step_name).console().response step = project.steps[index] if value is None: value = not bool(step.is_muted) step.is_muted = value return response.notify( kind='SUCCESS', code='STEP_MUTE_ENABLED' if step.is_muted else 'STEP_MUTE_DISABLED', message='Muting has been {}'.format( 'enabled' if step.is_muted else 'disabled')).kernel( project=project.kernel_serialize()).console().response
def echo_steps(response: Response, project: Project): """ :param response: :param project: :return: """ if len(project.steps) < 1: response.update(steps=[]).notify( kind='SUCCESS', code='ECHO_STEPS', message='No steps in project').console(""" [NONE]: This project does not have any steps yet. To add a new step use the command: steps add [YOUR_STEP_NAME] and a new step will be created in this project. """, whitespace=1) return response.update(steps=[ps.kernel_serialize() for ps in project.steps]).notify( kind='SUCCESS', code='ECHO_STEPS').console_header( 'Project Steps', level=3).console('\n'.join([ '* {}'.format(ps.definition.name) for ps in project.steps ]), indent_by=2, whitespace_bottom=1)
def fetch_recent(response: Response) -> str: """ :return: """ recent_paths = environ.configs.fetch('recent_paths', []) if len(recent_paths) < 1: response.fail( code='NO_RECENT_PROJECTS', message='There are no recent projects available' ).console() return None index, path = query.choice( 'Recently Opened Projects', 'Choose a project', recent_paths + ['Cancel'], 0 ) if index == len(recent_paths): return None return path
def synchronize_step_names( project: 'projects.Project', insert_index: int = None ) -> Response: """ :param project: :param insert_index: """ response = Response() response.returned = dict() if not project.naming_scheme: return response create_mapper_func = functools.partial( create_rename_entry, insertion_index=insert_index ) step_renames = list([create_mapper_func(s) for s in project.steps]) step_renames = list(filter(lambda sr: (sr is not None), step_renames)) if not step_renames: return response try: backup_path = create_backup(project) except Exception as err: return response.fail( code='RENAME_BACKUP_ERROR', message='Unable to create backup name', error=err ).response try: step_renames = list([stash_source(sr) for sr in step_renames]) step_renames = list([unstash_source(sr) for sr in step_renames]) except Exception as err: return response.fail( code='RENAME_FILE_ERROR', message='Unable to rename files', error=err ).response response.returned = update_steps(project, step_renames) project.save() try: os.remove(backup_path) except PermissionError: pass return response
def fetch_last(response: Response) -> typing.Union[str, None]: """ Returns the last opened project path if such a path exists """ recent_paths = environ.configs.fetch('recent_paths', []) if len(recent_paths) < 1: response.fail( code='NO_RECENT_PROJECTS', message='No projects have been opened recently').console() return None return recent_paths[0]
def fetch_last(response: Response) -> typing.Union[str, None]: """ Returns the last opened project path if such a path exists """ recent_paths = environ.configs.fetch('recent_paths', []) if len(recent_paths) < 1: response.fail( code='NO_RECENT_PROJECTS', message='No projects have been opened recently' ).console() return None return recent_paths[0]
def get_parser( target_module, raw_args: typing.List[str], assigned_args: dict ) -> typing.Tuple[ArgumentParser, Response]: """ :param target_module: :param raw_args: :param assigned_args: :return: """ response = Response() description = None if hasattr(target_module, 'DESCRIPTION'): description = getattr(target_module, 'DESCRIPTION') parser = ArgumentParser( prog=target_module.NAME, add_help=False, description=description ) parser.add_argument( '-h', '--help', dest='show_help', action='store_true', default=False, help=cli.reformat( """ Print this help information instead of running the command """ ) ) if not hasattr(target_module, 'populate'): return parser, response try: getattr(target_module, 'populate')(parser, raw_args, assigned_args) except Exception as err: response.fail( code='ARGS_PARSE_ERROR', message='Unable to parse command arguments', error=err, name=target_module.NAME ).console(whitespace=1) return parser, response
def remove_step(response: Response, project: 'projects.Project', name: str, keep_file: bool = False) -> Response: """ :param response: :param project: :param name: :param keep_file: :return: """ step = project.remove_step(name) if not step: return response.fail( code='NO_SUCH_STEP', message='Step "{}" not found. Unable to remove.'.format( name)).kernel(name=name).console(whitespace=1).response project.save() project.write() if not keep_file: os.remove(step.source_path) res = step_support.synchronize_step_names(project) response.consume(res) if response.failed: return response step_renames = res.returned removed_name = 'REMOVED--{}'.format(uuid.uuid4()) step_renames[name] = dict(name=removed_name, title='') step_changes = [ dict(name=removed_name, filename=step.filename, action='removed') ] return response.update( project=project.kernel_serialize(), step_changes=step_changes, step_renames=step_renames).notify( kind='SUCCESS', code='STEP_REMOVED', message='Removed "{}" step from project'.format(name)).console( whitespace=1).response
def test_initialize_results(self, initialize_results_path: MagicMock): """Should initialize paths for project""" response = Response() project = MagicMock() result = opener.initialize_results(response, project) self.assertTrue(result) self.assertEqual(1, initialize_results_path.call_count)
def get_project(response: Response): """ :return: """ project = cauldron.project.internal_project if not project: response.fail(code='NO_OPEN_PROJECT', message='No project opened').console(""" [ERROR]: No project has been opened. Use the "open" command to open a project, or the "create" command to create a new one. """, whitespace=1) return None return project
def test_initialize_results_abort(self, initialize_results_path: MagicMock): """Should abort initializing project has no results path""" response = Response() project = MagicMock() project.results_path = None result = opener.initialize_results(response, project) self.assertTrue(result) self.assertEqual(0, initialize_results_path.call_count)
def test_initialize_results_error(self, initialize_results_path: MagicMock): """Should fail to initialize paths for project""" initialize_results_path.side_effect = ValueError('FAKE') response = Response() project = MagicMock() result = opener.initialize_results(response, project) self.assertFalse(result) self.assertTrue(response.failed) self.assertEqual(1, initialize_results_path.call_count)
def fetch_recent(response: Response) -> str: """ :return: """ recent_paths = environ.configs.fetch('recent_paths', []) if len(recent_paths) < 1: response.fail( code='NO_RECENT_PROJECTS', message='There are no recent projects available').console() return None index, path = query.choice('Recently Opened Projects', 'Choose a project', recent_paths + ['Cancel'], 0) if index == len(recent_paths): return None return path
def get_parser(module, raw_args: typing.List[str], assigned_args: dict) -> typing.Tuple[ArgumentParser, Response]: """ :param module: :param raw_args: :param assigned_args: :return: """ response = Response() description = None if hasattr(module, 'DESCRIPTION'): description = getattr(module, 'DESCRIPTION') parser = ArgumentParser(prog=module.NAME, add_help=False, description=description) parser.add_argument('-h', '--help', dest='show_help', action='store_true', default=False, help=cli.reformat(""" Print this help information instead of running the command """)) if not hasattr(module, 'populate'): return parser, response try: getattr(module, 'populate')(parser, raw_args, assigned_args) except Exception as err: response.fail(code='ARGS_PARSE_ERROR', message='Unable to parse command arguments', error=err, name=module.NAME).console(whitespace=1) return parser, response
def check_status( response: Response, project: Project, step: ProjectStep, force: bool = False ) -> str: """ :param response: :param project: :param step: :param force: :return: """ path = step.source_path if step.is_muted: environ.log('[{}]: Muted (skipped)'.format(step.definition.name)) return SKIP_STATUS if not os.path.exists(path): response.fail( code='MISSING_SOURCE_FILE', message='Source file not found "{}"'.format(path), id=step.definition.name, path=path ).console( '[{id}]: Not found "{path}"'.format( id=step.definition.name, path=path ) ) return ERROR_STATUS if not force and not step.is_dirty(): environ.log('[{}]: Nothing to update'.format(step.definition.name)) return SKIP_STATUS return OK_STATUS
def echo_steps(response: Response, project: Project): """ :param response: :param project: :return: """ if len(project.steps) < 1: response.update( steps=[] ).notify( kind='SUCCESS', code='ECHO_STEPS', message='No steps in project' ).console( """ [NONE]: This project does not have any steps yet. To add a new step use the command: steps add [YOUR_STEP_NAME] and a new step will be created in this project. """, whitespace=1 ) return response.update( steps=[ps.kernel_serialize() for ps in project.steps] ).notify( kind='SUCCESS', code='ECHO_STEPS' ).console_header( 'Project Steps', level=3 ).console( '\n'.join(['* {}'.format(ps.definition.name) for ps in project.steps]), indent_by=2, whitespace_bottom=1 )
def toggle_muting( response: Response, project: Project, step_name: str, value: bool = None ) -> Response: """ :param response: :param project: :param step_name: :param value: :return: """ index = project.index_of_step(step_name) if index is None: return response.fail( code='NO_SUCH_STEP', message='No step found with name: "{}"'.format(step_name) ).kernel( name=step_name ).console().response step = project.steps[index] if value is None: value = not bool(step.is_muted) step.is_muted = value return response.notify( kind='SUCCESS', code='STEP_MUTE_ENABLED' if step.is_muted else 'STEP_MUTE_DISABLED', message='Muting has been {}'.format( 'enabled' if step.is_muted else 'disabled' ) ).kernel( project=project.kernel_serialize() ).console().response
def get_project(response: Response): """ :return: """ project = cauldron.project.internal_project if not project: response.fail( code='NO_OPEN_PROJECT', message='No project opened' ).console( """ [ERROR]: No project has been opened. Use the "open" command to open a project, or the "create" command to create a new one. """, whitespace=1 ) return None return project
def test_explode_line(self): """ """ r = Response('TEST').update(test_info='More test information') m = messages.Message('Some-Message', 'This is a test', 'Message that will be turned into a string', response=r) m = str(m) self.assertGreater( len(m), 0, messages.Message('Message to String', 'Unable to convert message to string'))
def synchronize_step_names(project: 'projects.Project', insert_index: int = None) -> Response: """ :param project: :param insert_index: """ response = Response() response.returned = dict() if not project.naming_scheme: return response create_mapper_func = functools.partial(create_rename_entry, insertion_index=insert_index) step_renames = list([create_mapper_func(s) for s in project.steps]) step_renames = list(filter(lambda sr: (sr is not None), step_renames)) if not step_renames: return response try: backup_path = create_backup(project) except Exception as err: return response.fail(code='RENAME_BACKUP_ERROR', message='Unable to create backup name', error=err).response try: step_renames = list([stash_source(sr) for sr in step_renames]) step_renames = list([unstash_source(sr) for sr in step_renames]) except Exception as err: return response.fail(code='RENAME_FILE_ERROR', message='Unable to rename files', error=err).response response.returned = update_steps(project, step_renames) project.save() try: os.remove(backup_path) except PermissionError: pass return response
def check_connection(url: str, force: bool) -> Response: """ """ response = Response() if force: return response ping = '{}/ping'.format(url) response.notify( kind='STARTING', code='CONNECTING', message='Establishing connection to: {}'.format(url) ).console( whitespace_top=1 ) try: result = requests.get(ping) if result.status_code != 200: raise request_exceptions.ConnectionError() except request_exceptions.InvalidURL as error: return response.fail( code='INVALID_URL', message='Invalid connection URL. Unable to establish connection', error=error ).console( whitespace=1 ).response except request_exceptions.ConnectionError as error: return response.fail( code='CONNECTION_ERROR', message='Unable to connect to remote cauldron host', error=error ).console( whitespace=1 ).response except Exception as error: return response.fail( code='CONNECT_COMMAND_ERROR', message='Failed to connect to the remote cauldron host', error=error ).console( whitespace=1 ).response
def run_step( response: Response, project: Project, step: typing.Union[ProjectStep, str], force: bool = False ) -> bool: """ :param response: :param project: :param step: :param force: :return: """ step = get_step(project, step) if step is None: return False status = check_status(response, project, step, force) if status == ERROR_STATUS: return False step.error = None if status == SKIP_STATUS: return True os.chdir(os.path.dirname(step.source_path)) project.current_step = step step.report.clear() step.dom = None step.is_running = True step.progress_message = None step.progress = 0 # Set the top-level display and cache values to the current project values # before running the step for availability within the step scripts cauldron.shared = cauldron.project.shared redirection.enable(step) try: result = _execute_step(project, step) except Exception as error: result = dict( success=False, message='{}'.format(error), html_message='<pre>{}</pre>'.format(error) ) os.chdir(os.path.expanduser('~')) step.mark_dirty(not result['success']) step.error = result.get('html_message') step.last_modified = time.time() if result['success'] else 0.0 step.is_running = False step.progress = 0 step.progress_message = None step.dumps() # Make sure this is called prior to printing response information to the # console or that will come along for the ride redirection.disable(step) if result['success']: environ.log('[{}]: Updated'.format(step.definition.name)) else: response.fail( message='Step execution error', code='EXECUTION_ERROR', project=project.kernel_serialize(), step_name=step.definition.name ).console_raw(result['message']) return result['success']
def create_step(response: Response, project: Project, name: str, position: typing.Union[str, int], title: str = None) -> Response: """ :param response: :param project: :param name: :param position: :param title: :return: """ name = name.strip('"') title = title.strip('"') if title else title index = index_from_location(response, project, position) if index is None: index = len(project.steps) name_parts = naming.explode_filename(name, project.naming_scheme) if not project.naming_scheme and not name_parts['name']: name_parts['name'] = naming.find_default_filename( [s.definition.name for s in project.steps]) name_parts['index'] = index name = naming.assemble_filename(scheme=project.naming_scheme, **name_parts) res = step_support.synchronize_step_names(project, index) response.consume(res) if response.failed: return response step_renames = res.returned step_data = {'name': name} if title: step_data['title'] = title result = project.add_step(step_data, index=index) if not os.path.exists(result.source_path): contents = ('import cauldron as cd\n\n' if result.source_path.endswith('.py') else '') with open(result.source_path, 'w+') as f: f.write(contents) project.save() project.write() index = project.steps.index(result) step_changes = [ dict(name=result.definition.name, filename=result.filename, action='added', step=writing.step_writer.serialize(result)._asdict(), after=None if index < 1 else project.steps[index - 1].definition.name) ] return response.update( project=project.kernel_serialize(), step_name=result.definition.name, step_path=result.source_path, step_changes=step_changes, step_renames=step_renames).notify( kind='CREATED', code='STEP_CREATED', message='"{}" step has been created'.format( result.definition.name)).console(whitespace=1).response
def open_project( path: str, forget: bool = False, results_path: str = None ) -> Response: """ :param path: :param forget: :param results_path: :return: """ response = Response() try: # Try to close any open projects before opening a new one. runner.close() except Exception: # pragma: no cover pass path = environ.paths.clean(path) if not project_exists(response, path): return response.fail( code='PROJECT_NOT_FOUND', message='No project found at: "{}"'.format(path) ).console(whitespace=1).response if not load_project(response, path): return response.fail( code='PROJECT_NOT_LOADED', message='Unable to load project data' ).console(whitespace=1).response if not forget and not update_recent_paths(response, path): return response.fail( code='PROJECT_STATUS_FAILURE', message='Unable to update loaded project status' ).console(whitespace=1).response project = cauldron.project.get_internal_project() if results_path: project.results_path = results_path # Set the top-level display and cache values to the current project values # before running the step for availability within the step scripts cauldron.shared = cauldron.project.shared if not initialize_results(response, project): return response.fail( code='PROJECT_INIT_FAILURE', message='Unable to initialize loaded project' ).console(whitespace=1).response if not write_results(response, project): return response.fail( code='PROJECT_WRITE_FAILURE', message='Unable to write project notebook data' ).console(whitespace=1).response # Should no longer be needed because the source directory is included # in the library directories as of v0.4.7 # runner.add_library_path(project.source_directory) runner.reload_libraries(project.library_directories) return response.update( project=project.kernel_serialize() ).notify( kind='SUCCESS', code='PROJECT_OPENED', message='Opened project: {}'.format(path) ).console_header( project.title, level=2 ).console( """ PATH: {path} URL: {url} """.format(path=path, url=project.baked_url), whitespace=1 ).response
def modify_step(response: Response, project: Project, name: str, new_name: str = None, position: typing.Union[str, int] = None, title: str = None): """ :param response: :param project: :param name: :param new_name: :param position: :param title: :return: """ new_name = new_name if new_name else name old_index = project.index_of_step(name) new_index = index_from_location(response, project, position, old_index) if new_index > old_index: # If the current position of the step occurs before the new position # of the step, the new index has to be shifted by one to account for # the fact that this step will no longer be in this position when it # get placed in the position within the project new_index -= 1 old_step = project.remove_step(name) if not old_step: response.fail( code='NO_SUCH_STEP', message='Unable to modify unknown step "{}"'.format(name)).console( whitespace=1) return False source_path = old_step.source_path if os.path.exists(source_path): temp_path = '{}.cauldron_moving'.format(source_path) shutil.move(source_path, temp_path) else: temp_path = None res = step_support.synchronize_step_names(project, new_index) response.consume(res) step_renames = res.returned new_name_parts = naming.explode_filename(new_name, project.naming_scheme) new_name_parts['index'] = new_index if not project.naming_scheme and not new_name_parts['name']: new_name_parts['name'] = naming.find_default_filename( [s.definition.name for s in project.steps]) new_name = naming.assemble_filename(scheme=project.naming_scheme, **new_name_parts) step_data = {'name': new_name} if title is None: if old_step.definition.get('title'): step_data['title'] = old_step.definition.title else: step_data['title'] = title.strip('"') new_step = project.add_step(step_data, new_index) project.save() if not os.path.exists(new_step.source_path): if temp_path and os.path.exists(temp_path): shutil.move(temp_path, new_step.source_path) else: with open(new_step.source_path, 'w+') as f: f.write('') if new_index > 0: before_step = project.steps[new_index - 1].definition.name else: before_step = None step_renames[old_step.definition.name] = { 'name': new_step.definition.name, 'title': new_step.definition.title } step_changes = [ dict(name=new_step.definition.name, filename=new_step.filename, action='modified', after=before_step) ] response.update( project=project.kernel_serialize(), step_name=new_step.definition.name, step_changes=step_changes, step_renames=step_renames).notify( kind='SUCCESS', code='STEP_MODIFIED', message='Step modifications complete').console(whitespace=1) project.write() return True
def test_load_project_bad_2(self, runner_initialize, *args): runner_initialize.side_effect = ValueError() response = Response() self.assertFalse(opener.load_project(response, INVALID_PATH)) self.assertTrue(response.errors[0].code == 'PROJECT_INIT_FAILURE')
def test_load_project_bad(self, runner_initialize, *args): runner_initialize.side_effect = FileNotFoundError() response = Response() self.assertFalse(opener.load_project(response, INVALID_PATH)) self.assertTrue(response.errors[0].code == 'PROJECT_NOT_FOUND')
def test_not_exists_load(self, *args): """ should return False when the project does not exist """ self.assertFalse(opener.load_project(Response(), INVALID_PATH))
def modify_step( response: Response, project: Project, name: str, new_name: str = None, position: typing.Union[str, int] = None, title: str = None ): """ :param response: :param project: :param name: :param new_name: :param position: :param title: :return: """ new_name = new_name if new_name else name old_index = project.index_of_step(name) new_index = index_from_location(response, project, position, old_index) if new_index > old_index: # If the current position of the step occurs before the new position # of the step, the new index has to be shifted by one to account for # the fact that this step will no longer be in this position when it # get placed in the position within the project new_index -= 1 old_step = project.remove_step(name) if not old_step: response.fail( code='NO_SUCH_STEP', message='Unable to modify unknown step "{}"'.format(name) ).console( whitespace=1 ) return False source_path = old_step.source_path if os.path.exists(source_path): temp_path = '{}.cauldron_moving'.format(source_path) shutil.move(source_path, temp_path) else: temp_path = None res = step_support.synchronize_step_names(project, new_index) response.consume(res) step_renames = res.returned new_name_parts = naming.explode_filename(new_name, project.naming_scheme) new_name_parts['index'] = new_index if not project.naming_scheme and not new_name_parts['name']: new_name_parts['name'] = naming.find_default_filename( [s.definition.name for s in project.steps] ) new_name = naming.assemble_filename( scheme=project.naming_scheme, **new_name_parts ) step_data = {'name': new_name} if title is None: if old_step.definition.title: step_data['title'] = old_step.definition.title else: step_data['title'] = title.strip('"') new_step = project.add_step(step_data, new_index) project.save() if not os.path.exists(new_step.source_path): if temp_path and os.path.exists(temp_path): shutil.move(temp_path, new_step.source_path) else: with open(new_step.source_path, 'w+') as f: f.write('') if new_index > 0: before_step = project.steps[new_index - 1].definition.name else: before_step = None step_renames[old_step.definition.name] = { 'name': new_step.definition.name, 'title': new_step.definition.title } step_changes = [dict( name=new_step.definition.name, filename=new_step.filename, action='modified', after=before_step )] response.update( project=project.kernel_serialize(), step_name=new_step.definition.name, step_changes=step_changes, step_renames=step_renames ).notify( kind='SUCCESS', code='STEP_MODIFIED', message='Step modifications complete' ).console( whitespace=1 ) project.write() return True
def create_step( response: Response, project: Project, name: str, position: typing.Union[str, int], title: str = None ) -> Response: """ :param response: :param project: :param name: :param position: :param title: :return: """ name = name.strip('"') title = title.strip('"') if title else title index = index_from_location(response, project, position) if index is None: index = len(project.steps) name_parts = naming.explode_filename(name, project.naming_scheme) if not project.naming_scheme and not name_parts['name']: name_parts['name'] = naming.find_default_filename( [s.definition.name for s in project.steps] ) name_parts['index'] = index name = naming.assemble_filename( scheme=project.naming_scheme, **name_parts ) res = step_support.synchronize_step_names(project, index) response.consume(res) if response.failed: return response step_renames = res.returned step_data = {'name': name} if title: step_data['title'] = title result = project.add_step(step_data, index=index) if not os.path.exists(result.source_path): contents = ( 'import cauldron as cd\n\n' if result.source_path.endswith('.py') else '' ) with open(result.source_path, 'w+') as f: f.write(contents) project.save() project.write() index = project.steps.index(result) step_changes = [dict( name=result.definition.name, filename=result.filename, action='added', step=writing.step_writer.serialize(result)._asdict(), after=None if index < 1 else project.steps[index - 1].definition.name )] return response.update( project=project.kernel_serialize(), step_name=result.definition.name, step_path=result.source_path, step_changes=step_changes, step_renames=step_renames ).notify( kind='CREATED', code='STEP_CREATED', message='"{}" step has been created'.format(result.definition.name) ).console( whitespace=1 ).response
def run_step( response: Response, project: Project, step: typing.Union[ProjectStep, str], force: bool = False ) -> bool: """ :param response: :param project: :param step: :param force: :return: """ step = get_step(project, step) if step is None: return False status = check_status(response, project, step, force) if status == ERROR_STATUS: return False step.error = None if status == SKIP_STATUS: return True os.chdir(os.path.dirname(step.source_path)) project.current_step = step step.report.clear() step.dom = None step.is_visible = True step.is_running = True step.progress_message = None step.progress = 0 step.sub_progress_message = None step.sub_progress = 0 step.start_time = datetime.utcnow() step.end_time = None # Set the top-level display and cache values to the current project values # before running the step for availability within the step scripts cauldron.shared = cauldron.project.shared redirection.enable(step) try: result = _execute_step(project, step) except Exception as error: result = dict( success=False, message='{}'.format(error), html_message='<pre>{}</pre>'.format(error) ) step.end_time = datetime.utcnow() os.chdir(os.path.expanduser('~')) step.mark_dirty(not result['success']) step.error = result.get('html_message') step.last_modified = time.time() if result['success'] else 0.0 step.is_running = False step.progress = 0 step.progress_message = None step.dumps() # Make sure this is called prior to printing response information to the # console or that will come along for the ride redirection.disable(step) step.project.stop_condition = result.get( 'stop_condition', StopCondition(False, False) ) if result['success']: environ.log('[{}]: Updated in {}'.format( step.definition.name, step.get_elapsed_timestamp() )) else: response.fail( message='Step execution error', code='EXECUTION_ERROR', project=project.kernel_serialize(), step_name=step.definition.name ).console_raw(result['message']) return result['success']
def test_not_exists(self): """ should return False when the project does not exist """ self.assertFalse(opener.project_exists(Response(), INVALID_PATH))
def remove_step( response: Response, project: 'projects.Project', name: str, keep_file: bool = False ) -> Response: """ :param response: :param project: :param name: :param keep_file: :return: """ step = project.remove_step(name) if not step: return response.fail( code='NO_SUCH_STEP', message='Step "{}" not found. Unable to remove.'.format(name) ).kernel( name=name ).console( whitespace=1 ).response project.save() project.write() if not keep_file: os.remove(step.source_path) res = step_support.synchronize_step_names(project) response.consume(res) if response.failed: return response step_renames = res.returned removed_name = 'REMOVED--{}'.format(uuid.uuid4()) step_renames[name] = dict( name=removed_name, title='' ) step_changes = [dict( name=removed_name, filename=step.filename, action='removed' )] return response.update( project=project.kernel_serialize(), step_changes=step_changes, step_renames=step_renames ).notify( kind='SUCCESS', code='STEP_REMOVED', message='Removed "{}" step from project'.format(name) ).console( whitespace=1 ).response
def open_project( path: str, forget: bool = False, results_path: str = None ) -> Response: """ :param path: :param forget: :param results_path: :return: """ response = Response() try: runner.close() except Exception: pass path = environ.paths.clean(path) if not project_exists(response, path): return response.fail( code='PROJECT_NOT_FOUND', message='No project found at: "{}"'.format(path) ).console(whitespace=1).response if not load_project(response, path): return response.fail( code='PROJECT_NOT_LOADED', message='Unable to load project data' ).console(whitespace=1).response if not forget and not update_recent_paths(response, path): return response.fail( code='PROJECT_STATUS_FAILURE', message='Unable to update loaded project status' ).console(whitespace=1).response project = cauldron.project.internal_project if results_path: project.results_path = results_path # Set the top-level display and cache values to the current project values # before running the step for availability within the step scripts cauldron.shared = cauldron.project.shared if not initialize_results(response, project): return response.fail( code='PROJECT_INIT_FAILURE', message='Unable to initialize loaded project' ).console(whitespace=1).response if not write_results(response, project): return response.fail( code='PROJECT_WRITE_FAILURE', message='Unable to write project notebook data' ).console(whitespace=1).response runner.add_library_path(project.source_directory) return response.update( project=project.kernel_serialize() ).notify( kind='SUCCESS', code='PROJECT_OPENED', message='Opened project: {}'.format(path) ).console_header( project.title, level=2 ).console( """ PATH: {path} URL: {url} """.format(path=path, url=project.baked_url), whitespace=1 ).response