Exemple #1
0
  def __call__(self, parser, namespace, values, option_string=None):
    # figure out what options are set
    parse_files = hasattr(namespace, 'files')
    parse_phil = hasattr(namespace, 'phil')
    parse_dir = hasattr(namespace, 'dir')

    # get previous values or define default
    if ( parse_files and (getattr(namespace, 'files') is not None) ):
      files = namespace.files
    else:
      files = list()
    if ( parse_phil and (getattr(namespace, 'phil') is not None) ):
      phil = namespace.phil
    else:
      phil = list()
    if ( parse_dir and (getattr(namespace, 'dir') is not None) ):
      directory = namespace.dir
    else:
      directory = list()
    if ( hasattr(namespace, 'unknown') and
         (getattr(namespace, 'unknown') is not None) ):
      unknown = namespace.unknown
    else:
      unknown = list()

    # separate values
    for value in values:
      if (os.path.isfile(value)):
        files.append(value)
      elif ( (isinstance(value, str)) and
             ('=' in value) ):
        phil.append(value)
      elif (os.path.isdir(value)):
        directory.append(value)
      else:
        unknown.append(value)

    # update options
    if (parse_files):
      setattr(namespace, 'files', files)
    else:
      unknown.extend(files)
    if (parse_phil):
      setattr(namespace, 'phil', phil)
    else:
      unknown.extend(phil)
    if (parse_dir):
      setattr(namespace, 'dir', directory)
    else:
      unknown.extend(directory)

    # store unknown values for custom processing (if available)
    setattr(namespace, 'unknown', unknown)
Exemple #2
0
    def process_phil(self, phil_list):
        ''''
    Process PHIL arguments
    Currently only handles command-line changes
    Will add inclusion of PHIL files from data_manager first, then
    command-line options
    '''
        print('Processing PHIL parameters:', file=self.logger)
        print('-' * self.text_width, file=self.logger)
        print('', file=self.logger)

        printed_something = False

        data_sources = list()
        sources = list()
        unused_phil = list()

        # PHIL files are processed in order from command-line
        if (self.data_manager.has_phils()):
            phil_names = self.data_manager.get_phil_names()
            phil = list()
            print('  Adding PHIL files:', file=self.logger)
            print('  ------------------', file=self.logger)
            for name in phil_names:
                # remove DataManager scope since input files are already loaded
                phil_scope = self.data_manager.get_phil(name)
                for phil_object in phil_scope.objects:
                    if (phil_object.name == 'data_manager'):
                        phil_scope.objects.remove(phil_object)
                phil.append(phil_scope)
                print('    %s' % name, file=self.logger)
            data_sources.extend(phil)
            print('', file=self.logger)
            printed_something = True

        # command-line PHIL arguments override any previous settings and are
        # processed in given order
        def custom_processor(arg):
            unused_phil.append(arg)
            return True

        if (len(phil_list) > 0):
            interpreter = self.master_phil.command_line_argument_interpreter(
                home_scope='')
            print('  Adding command-line PHIL:', file=self.logger)
            print('  -------------------------', file=self.logger)
            for phil in phil_list:
                print('    %s' % phil, file=self.logger)
            print('', file=self.logger)
            printed_something = True
            working = interpreter.process_args(
                phil_list, custom_processor=custom_processor)
            if (len(working) > 0):
                sources.extend(working)
        if (self.namespace.overwrite):  # override overwrite if True
            sources.append(iotbx.phil.parse('output.overwrite=True'))
        if ((len(data_sources) + len(sources)) > 0):
            self.working_phil, more_unused_phil = self.master_phil.fetch(
                sources=data_sources + sources, track_unused_definitions=True)
            unused_phil.extend(more_unused_phil)
        else:
            self.working_phil = self.master_phil

        # show unrecognized parameters and abort
        if (len(unused_phil) > 0):
            print('  Unrecognized PHIL parameters:', file=self.logger)
            print('  -----------------------------', file=self.logger)
            for phil in unused_phil:
                print('    %s' % phil, file=self.logger)
            print('', file=self.logger)
            error_message = 'Some PHIL parameters are not recognized by %s.\n' % \
                            self.prog
            error_message += wordwrap(
                'Please run this program with the --show-defaults option to see what parameters are available.',
                max_chars=self.text_width) + '\n'
            error_message += wordwrap(
                'PHIL parameters in files should be fully specified (e.g. "output.overwrite" instead of just "overwrite")',
                max_chars=self.text_width) + '\n'
            raise Sorry(error_message)

        if (not printed_something):
            print('  No PHIL parameters found', file=self.logger)
            print('', file=self.logger)
Exemple #3
0
    def process_phil(self, phil_list):
        ''''
    Process PHIL arguments
    Also checks PHIL arguments (command line and files) for parameters that
    specify files (.type = path)
    '''
        print('Processing PHIL parameters:', file=self.logger)
        print('-' * self.text_width, file=self.logger)
        print('', file=self.logger)

        printed_something = False

        data_sources = list()
        sources = list()
        unused_phil = list()

        # PHIL files are processed in order from command-line
        if (self.data_manager.has_phils()):
            phil_names = self.data_manager.get_phil_names()
            phil = list()
            print('  Adding PHIL files:', file=self.logger)
            print('  ------------------', file=self.logger)
            for name in phil_names:
                # remove DataManager scope since input files are already loaded
                phil_scope = self.data_manager.get_phil(name)
                for phil_object in phil_scope.objects:
                    if (phil_object.name == 'data_manager'):
                        phil_scope.objects.remove(phil_object)
                phil.append(phil_scope)
                print('    %s' % name, file=self.logger)
            data_sources.extend(phil)
            print('', file=self.logger)
            printed_something = True

        # command-line PHIL arguments override any previous settings and are
        # processed in given order
        def custom_processor(arg):
            unused_phil.append(arg)
            return True

        if (len(phil_list) > 0):
            interpreter = self.master_phil.command_line_argument_interpreter(
                home_scope='')
            print('  Adding command-line PHIL:', file=self.logger)
            print('  -------------------------', file=self.logger)
            for phil in phil_list:
                print('    %s' % phil, file=self.logger)
            print('', file=self.logger)
            printed_something = True
            working = interpreter.process_args(
                phil_list, custom_processor=custom_processor)
            if (len(working) > 0):
                sources.extend(working)
        if (self.namespace.overwrite):  # override overwrite if True
            sources.append(iotbx.phil.parse('output.overwrite=True'))
        if ((len(data_sources) + len(sources)) > 0):
            self.working_phil, more_unused_phil = self.master_phil.fetch(
                sources=data_sources + sources, track_unused_definitions=True)
            unused_phil.extend(more_unused_phil)
        else:
            self.working_phil = self.master_phil.fetch()

        # show unrecognized parameters and abort
        if (len(unused_phil) > 0):
            print('  Unrecognized PHIL parameters:', file=self.logger)
            print('  -----------------------------', file=self.logger)
            for phil in unused_phil:
                print('    %s' % phil, file=self.logger)
            print('', file=self.logger)
            error_message = 'Some PHIL parameters are not recognized by %s.\n' % \
                            self.prog
            error_message += wordwrap(
                'Please run this program with the --show-defaults option to see what parameters are available.',
                max_chars=self.text_width) + '\n'
            error_message += wordwrap(
                'PHIL parameters in files should be fully specified (e.g. "output.overwrite" instead of just "overwrite")',
                max_chars=self.text_width) + '\n'
            raise Sorry(error_message)

        # process input phil for file/directory defintions and add to DataManager
        # Note: if a PHIL file is input as a PHIL parameter, the contents of the
        # file will NOT be parsed and validated. The PHIL file should be provided
        # as a command-line argument. This is mostly for finding data files
        # defined by PHIL parameters that should be added to the DataManager
        diff_phil = self.master_phil.fetch_diff(self.working_phil)
        paths = self.check_phil_for_paths(diff_phil)
        if (len(paths) > 0):
            files = list()
            dirs = list()
            for path in paths:
                if (path is not None):
                    if (os.path.isfile(path)):
                        files.append(path)
                    elif (os.path.isdir(path)):
                        dirs.append(path)
            if (self.parse_files):
                self.process_files(files,
                                   message='Processing files from PHIL:')
            if (self.parse_dir):
                self.process_dir(dirs,
                                 message='Processing directories from PHIL:')

        if (not printed_something):
            print('  No PHIL parameters found', file=self.logger)
            print('', file=self.logger)
Exemple #4
0
    def process_phil(self, phil_list):
        ''''
    Process PHIL arguments
    Currently only handles command-line changes
    Will add inclusion of PHIL files from data_manager first, then
    command-line options
    '''
        print('Processing PHIL parameters:', file=self.logger)
        print('-' * 79, file=self.logger)
        print('', file=self.logger)

        printed_something = False

        data_sources = list()
        sources = list()
        unused_phil = list()

        # PHIL files are processed in order from command-line
        if (self.data_manager.has_phils()):
            phil_names = self.data_manager.get_phil_names()
            phil = list()
            for name in phil_names:
                phil.append(self.data_manager.get_phil(name))
            data_sources.extend(phil)

        # command-line PHIL arguments override any previous settings
        def custom_processor(arg):
            unused_phil.append(arg)
            return True

        interpreter = self.master_phil.command_line_argument_interpreter(
            home_scope='')
        working = interpreter.process_args(phil_list,
                                           custom_processor=custom_processor)
        if (len(working) > 0):
            sources.extend(working)
        if (self.namespace.overwrite):  # override overwrite if True
            sources.append(iotbx.phil.parse('output.overwrite=True'))
        self.working_phil, more_unused_phil = self.master_phil.fetch(
            sources=data_sources + sources, track_unused_definitions=True)
        unused_phil.extend(more_unused_phil)

        try:
            phil_diff = self.master_phil.fetch_diff(self.working_phil)
        except RuntimeError as err:
            raise Sorry(err)
        is_different = (len(phil_diff.as_str()) > 0)

        # show differences
        if (is_different):
            print('  Non-default PHIL parameters:', file=self.logger)
            print('  ----------------------------', file=self.logger)
            phil_diff.show(prefix='  ', out=self.logger)
            printed_something = True

        # write differences
        if (self.namespace.write_modified):
            if (is_different):
                self.data_manager.write_phil_file(
                    self.modified_filename,
                    phil_diff.as_str(),
                    overwrite=self.namespace.overwrite)
            else:
                print('  No PHIL modifications to write', file=self.logger)
                printed_something = True

        # show unrecognized parameters and abort
        if (len(unused_phil) > 0):
            print('', file=self.logger)
            print('  Unrecognized PHIL parameters:', file=self.logger)
            print('  -----------------------------', file=self.logger)
            for phil in unused_phil:
                print('  %s' % phil, file=self.logger)
            print('', file=self.logger)
            error_message = 'Some PHIL parameters are not recognized by %s.\n' % \
                            self.prog
            error_message += 'Please run this program with the --show-defaults option to see what parameters are available.\n'
            error_message += 'PHIL parameters in files should be fully specified (e.g. "output.overwrite" instead of just "overwrite")'
            raise Sorry(error_message)

        if (not printed_something):
            print('  No PHIL parameters found', file=self.logger)
        print('', file=self.logger)

        # show final processed phil scope
        try:
            data_diff = self.data_manager.master_phil.fetch_diff(
                self.data_manager.export_phil_scope())
        except RuntimeError as err:
            raise Sorry(err)
        is_different = ((len(data_diff.as_str()) + len(phil_diff.as_str())) >
                        0)
        if (is_different):
            print('Final processed PHIL parameters:')
            print('-' * 79, file=self.logger)
            data_diff.show(prefix='  ', out=self.logger)
            phil_diff.show(prefix='  ', out=self.logger)

        # write all parameters (DataManager + Program)
        if (self.namespace.write_all):
            all_phil = self.data_manager.export_phil_scope().as_str()
            all_phil += self.working_phil.as_str(expert_level=3)
            self.data_manager.write_phil_file(
                self.all_filename,
                all_phil,
                overwrite=self.namespace.overwrite)

        print('', file=self.logger)