Exemple #1
0
 def run_gen(self) -> Iterator[IterativeResult]:
     logger.info(f'Running {self.run_items} with cases')
     for case in self.cases:
         if not self.should_run(case):
             continue
         result = self._run_case(case)
         in_out_tup = (case, result)
         yield in_out_tup
    def _run_one_class(self, section_path_str: str) -> Result:
        with StackTracker(section_path_str, base_section_path_str=self._manager_name):
            klass, config_dict = self._get_func_and_config(section_path_str)
            obj = self._get_one_obj_with_config(section_path_str)

            logger.info(f'Running class {section_path_str}({dict_as_function_kwarg_str(config_dict)})')
            result = obj()
            logger.info(f'Result:\n{result}\n')
        self._add_to_config_dependencies_if_necessary(section_path_str)
        return result
Exemple #3
0
def report_runner_exceptions(runner_exceptions: List[RunnerException]) -> None:
    if len(runner_exceptions) == 0:
        logger.info(
            '\n\nEverything ran successfully, no exceptions to report.\n\n')
        return

    sp_strs = ', '.join(
        [str(exc.section_path_str) for exc in runner_exceptions])
    full_exc_str = f'Exception summary for running {sp_strs} (exceptions were also shown when raised):\n'
    full_exc_str += '\n\n'.join([str(exc) for exc in runner_exceptions])
    logger.error(full_exc_str)
Exemple #4
0
    def refresh(self, section_path_str: str):
        """
        Reloads from the existing file, then reapplies any config updates. Useful for when
        this config depends on the attribute of some other config which was updated.

        :param section_path_str: section path of item to be refreshed
        :return:
        """
        logger.info(f'Refreshing config for {section_path_str}')
        self.runner.refresh(section_path_str)
        logger.debug(f'Finished refreshing config for {section_path_str}')
    def _run_one_specific_class(self, section_path_str: str) -> Result:
        with StackTracker(section_path_str, base_section_path_str=self._manager_name):
            klass, config_dict = self._get_class_and_config(section_path_str)
            obj = self._get_one_obj_with_config(section_path_str)
            registrar = self._specific_class_registrar_map[klass]
            execute_attr = registrar.execute_attr
            func = getattr(obj, execute_attr)

            logger.info(f'Running class {section_path_str}({dict_as_function_kwarg_str(config_dict)})')
            result = func()
            logger.info(f'Result:\n{result}\n')
        self._add_to_config_dependencies_if_necessary(section_path_str)
        return result
Exemple #6
0
    def reload(self) -> None:
        """
        Useful for getting file system changes without having to start a new Python session. Also resets
        any locally defined configuration.

        Reloads functions from pipeline dict, scaffolds config files for any new functions,
        and updates configuration from files.

        Returns: None

        """
        logger.info(f'Reloading {self.name}')
        self._wipe_loaded_modules()
        self.load()
        logger.debug(f'Finished reloading {self.name}')
Exemple #7
0
 def run(self, collect_results: bool = True) -> IterativeResults:
     """
     :param collect_results: Whether to aggregate and return results, set to False to save memory
         if results are stored in some other way
     :return:
     """
     from pyfileconf.main import PipelineManager
     logger.info(f'Running {self.run_items} with cases')
     all_results = []
     for case in self.cases:
         if not self.should_run(case):
             continue
         result = self._run_case(case)
         if collect_results:
             in_out_tup = (case, result)
             all_results.append(in_out_tup)
Exemple #8
0
    def reset(self,
              section_path_str_or_view: 'StrOrView',
              allow_create: bool = False):
        """
        Resets a function or section config to default.

        To reset all configs, use .reload() instead.

        :param section_path_str_or_view:
        :return:
        """
        logger.info(f'Resetting config for {section_path_str_or_view}')
        section_path_str = self._get_section_path_str_from_section_path_str_or_view(
            section_path_str_or_view)
        self.runner.reset(section_path_str, allow_create=allow_create)
        logger.debug(
            f'Finished resetting config for {section_path_str_or_view}')
Exemple #9
0
    def _update(self,
                d_: dict = None,
                section_path_str: str = None,
                pyfileconf_persist: bool = True,
                **kwargs):
        """
        Update the configuration for an item by section path

        :param d_: dictionary of updates
        :param section_path_str: section path of item to be updated
        :param pyfileconf_persist: whether to make changes last through refreshing config
        :param kwargs: kwarg updates
        :return:
        """
        from pyfileconf.selector.models.itemview import is_item_view

        all_updates = {}
        if d_ is not None:
            all_updates.update(d_)
        all_updates.update(kwargs)
        logger.info(f'Updating {section_path_str} with config: {all_updates}')

        if section_path_str:
            # If any of the updates are putting an ItemView as the value, then
            # record that this config is dependent on the config referenced
            # by the ItemView
            all_updates = {**kwargs}
            if d_ is not None:
                all_updates.update(d_)
            full_sp = SectionPath.join(self.name, section_path_str)
            for value in all_updates.values():
                if is_item_view(value):
                    context.add_config_dependency(full_sp, value)

        self.runner.update(d_,
                           section_path_str,
                           pyfileconf_persist=pyfileconf_persist,
                           **kwargs)
        logger.debug(
            f'Finished updating {section_path_str} with config: {all_updates}')
Exemple #10
0
 def test_log_file(self):
     logger.info('woo')
     assert not os.path.exists(self.logs_path)
     pyfileconf.options.set_option('log_folder', self.logs_folder)
     logger.info('woo2')
     pyfileconf.options.reset()
     logger.info('woo3')
     assert os.path.exists(self.logs_path)
     with open(self.logs_path, 'r') as f:
         contents = f.read()
         assert contents == '[pyfileconf INFO]: woo2\n'
Exemple #11
0
    def create(self,
               section_path_str: str,
               func_or_class: Optional[Union[Callable, Type]] = None):
        """
        Create a new configuration entry dynamically rather than manually modifying dict file

        :param func_or_class: function or class to use to generate config
        :param section_path_str: section path at which the config should be stored
        :return:
        """
        logger.info(f'Creating config for {section_path_str}')
        section_path = SectionPath(section_path_str)

        if section_path[0] in self.specific_class_names:
            # Got path for a specific class dict, add to specific class dict
            if len(section_path) < 3:
                raise ValueError(
                    'when targeting a specific class dict, section path must have minimum length of '
                    '3, e.g. example_class.thing.stuff')
            if func_or_class is not None:
                raise ValueError(
                    'only pass func_or_class when targeting main pipeline dict, not specific class dict'
                )
            self._create_specific_class_dict_entry(section_path)
            full_sp = section_path
            registrar = self._registrar_dict[section_path[0]]
            klass = registrar.collection.klass
            if klass is None:
                raise ValueError(
                    f'must have specific class set, got None for class in {registrar}'
                )
            key_attr = registrar.collection.key_attr
            registrar_obj = convert_to_empty_obj_if_necessary(
                section_path[-1], klass, key_attr=key_attr)
            set_section_path_str = SectionPath.from_section_str_list(
                section_path[1:-1]).path_str
            scaffold_path_str = SectionPath.from_section_str_list(
                section_path[1:]).path_str
        else:
            # Got path for main pipeline dict, add to main pipeline dict
            if func_or_class is None:
                raise ValueError(
                    'when adding creating item in main pipeline dict, must pass function or class'
                )
            self._create_pipeline_dict_entry(section_path, func_or_class)
            name = func_or_class.__name__
            full_sp = SectionPath.join(section_path, name)
            mod, import_base = get_module_and_name_imported_from(func_or_class)
            obj_import = ObjectImportStatement([name], import_base)
            item = ast.Name(id=name)
            imports = ImportStatementContainer([obj_import])
            registrar_obj = ObjectView.from_ast_and_imports(item, imports)
            if self._general_registrar is None:
                raise ValueError('general registrar must be defined')
            registrar = self._general_registrar
            set_section_path_str = section_path_str
            scaffold_path_str = full_sp.path_str

        registrar.set(set_section_path_str, registrar_obj)
        registrar.scaffold_config_for(scaffold_path_str)
        self.reset(full_sp.path_str, allow_create=True)
        logger.debug(f'Finished creating config for {section_path_str}')
 def write(self, message):
     if message != '\n':
         logger.info(message)