class BaseModule(object): """Base Module all different modules have to be derived from. Please only use absolute imports (not relative ones like import ..module, since the module loader cannot handle this. """ __metaclass__ = ABCMeta def __init__(self): """ Set up parser and argument group for module.""" self.parser = SettingParser(add_help=False) self.arg_group = self.parser.add_argument_group(title=self.label, description=inspect.getdoc(self)) @ClassProperty @classmethod def label(cls): """ Label of the module.""" return cls.__name__ @abstractmethod def __call__(self, **args): """This method needs to be overloaded and will be called by the core.""" pass
def __init__(self): """ Set up parser and argument group for module.""" self.parser = SettingParser(add_help=False) self.arg_group = self.parser.add_argument_group(title=self.label, description=inspect.getdoc(self))
def build_config(self, input_config=None, log_level='info'): """ Parse arguments. To set log level, load additional module parsers etc. the sys.args[1:] are parsed multiple times. :return: dict of parsed args """ base_parser = SettingParser(add_help=False) base_parser_group = base_parser.add_argument_group(title='Base Parser', description='') base_parser_group.add_argument("--log-level", default=log_level, help="Set the log level.") base_parser_group.add_argument("--list-modules", action='store_true', help="List all available modules.") base_parser_group.add_argument("-l", "--load-config", default=[], nargs='+', help="Load json configs, with decreasing precedence, or a python scripts from file.") # Parse only log level to set it as early as possible args = vars(base_parser.parse_known_args()[0]) # Set log level log_level = getattr(logging, args['log_level'].upper(), None) if not isinstance(log_level, int): raise ValueError('Invalid log level: %s' % log_level) logging.basicConfig(format='%(message)s', level=log_level) # Discover all available modules self._all_modules = discover_modules() # If module list requested, print it and exit program if args['list_modules']: for label, module in self._all_modules.iteritems(): print label sys.exit(0) # Load configs/python scripts from files if requested file_config = ConfigDict() for item in args.pop('load_config', []): if item.endswith('.json'): merge(file_config, read_config(item)) elif item.endswith('.py'): log.info('Running python file {}'.format(item)) runpy.run_path(item) else: raise ValueError('The file type of {0} is not supported.'.format(item)) base_parser_group.add_argument("--input-modules", nargs='+', default=['RootModule'], help="Input modules .") base_parser_group.add_argument("--ana-modules", nargs='+', default=[], help="Analysis modules.") base_parser_group.add_argument("--output-modules", nargs='+', default=['PlotModule'], help="Output modules.") # Parse also the modules to add their parsers args = vars(base_parser.parse_known_args()[0]) module_parsers = [self._all_modules[name]().parser for name in args['input_modules'] + args['ana_modules'] + args['output_modules']] # Additional arguments for complete parser base_parser_group.add_argument("-p", "--print-config", default=False, action="store_true", help="Print out the JSON config before running Artus.") base_parser_group.add_argument("--store-json", type='bool', default=True, help="Save the config as json file.") base_parser_group.add_argument("--merge-args", nargs='+', default=[], help=("If json file configs and command line configs are provided the settings are " "merged for the provided args. Works only for list arguments.")) base_parser_group.add_argument('--output-path', default='plot.png', help='Path to output file.') base_parser_group.add_argument('--output-prefix', default='plots/', help='Prefix to output paths.') # Final parser consists of baseparser + active module parsers parser = SettingParser(parents=[base_parser] + module_parsers, description='''Plotting tool to read, manipulate and plot root objects.''') # Triggers before actual parameters are parsed. callbacks.trigger('before_parsing', config=file_config) # Final parsing of parameters args = vars(parser.parse_args()) # If a config was loaded, merge it with the args if file_config: provided_args = args.pop('provided_args') merge_args = args.pop('merge_args') merge(file_config, args, precedence_keys=provided_args, merge_keys=merge_args) config = file_config if input_config: merge(input_config, config, precedence_keys=provided_args, merge_keys=merge_args) config = input_config else: config = args # ConfigDict is just a simple wrapper around a dict with some helper functions. return ConfigDict(config)