Exemplo n.º 1
0
def system_to_others(system, database_directory, channel_dict):
    """
    Return references to records in other systems in the system's database file(s).
    It looks for record references in the field values and when it finds one
    it looks for it in the channel dictionary to determine what system it belongs to.
    The output is a list of tuples with the following information: record name,
    record field, referenced record name, referenced record field, list of systems
    where the referenced record name exists.
    :param system: system name
    :type system: str
    :param database_directory: database directory
    :type database_directory: str
    :param channel_dict: dictionary of known records
    :type channel_dict: dict
    :return: list tuples
    :rtype: list
    """
    output_list = []

    # Loop over all databases in the data directory
    for data_base_name in get_database_names(system, database_directory):

        # Open database name by file name. Open macro substitution file (if any).
        db = DatabaseFile(file_name=data_base_name)
        m = read_subs_file(data_base_name)

        # Loop over all records in the database
        for record in db.next_record():

            # Replace macros in the record name (if any)
            assert isinstance(record, EpicsRecord)
            record_name = record.get_name()
            if m is not None:
                record_name = m.replace_macros(record_name)

            # Loop over all the fields in the record. If the field value contains anything
            # matching a record name then append it to the output list, but only if it's
            # in the dictionary of known records and it belongs to a system other than the
            # one we are looking from.
            for field_name, field_value in record.get_fields():
                if m is not None:
                    field_value = m.replace_macros(field_value)
                # print field_name, field_value
                target_record_name, target_record_field = parse_field_value(field_value)
                if target_record_name is not None:
                    # print '-', record_name, record_field
                    if target_record_name in channel_dict and system not in channel_dict[target_record_name]:
                        output_list.append((target_record_name, target_record_field,
                                            # record.get_name(), field_name,
                                            record_name, field_name,
                                            channel_dict[target_record_name]))

    # return remove_duplicates(output_list)
    # print output_list
    return output_list
Exemplo n.º 2
0
def epics_record():
    """
    Fixture used to return a valid EpicsRecord object from single.db
    :return: epics record
    :rtype: EpicsRecord
    """
    df = DatabaseFile(file_name=SINGLE_RECORD)
    record = None
    for record in df.next_record():
        break
    return record
Exemplo n.º 3
0
def others_to_system(system, sys_list, database_directory, channel_dict):
    """
    :param system: system name we are looking for
    :type system: str
    :param sys_list: list of all systems
    :type sys_list: list
    :param database_directory: database directory
    :type database_directory: str
    :param channel_dict: dictionary of known records
    :type channel_dict: dict
    :return:
    :rtype: dict
    """
    print('others_to_system')
    # Remove the system from the list of systems (we don't want references to itself)
    other_systems = sys_list
    other_systems.remove(system)
    output_dict = {}

    # Loop over all systems
    for sys_name in other_systems:
        # Loop over all databases for that system
        for data_base_name in get_database_names(sys_name, database_directory):

            # Open database by name
            db = DatabaseFile(file_name=data_base_name)
            m = read_subs_file(data_base_name)
            # print '+', data_base_name, m

            # Loop over all records in the database
            for record in db.next_record():
                assert isinstance(record, EpicsRecord)
                # Loop over all fields in the database. If the field value contains anything
                # matching a record name then add it to the output dictionary, but only if it's
                # in the dictionary of known records and it belongs to a system we are looking for.
                for field_name, field_value in record.get_fields():
                    if m is not None:
                        field_value = m.replace_macros(field_value)
                    target_record_name, target_record_field = parse_field_value(field_value)
                    if target_record_name is not None:
                        if target_record_name in channel_dict and system in channel_dict[target_record_name]:
                            # print sys_name, target_record_name, target_record_field
                            if sys_name in output_dict:
                                output_dict[sys_name].append((target_record_name, target_record_field,
                                                              record.get_name(), field_name))
                            else:
                                output_dict[sys_name] = [(target_record_name, target_record_field,
                                                          record.get_name(), field_name)]
    # print output_dict
    return output_dict
Exemplo n.º 4
0
def larger_epics_database():
    df = DatabaseFile(file_name=LARGER_DATABASE)
    db = EpicsDatabase()
    for record in df.next_record():
        db.add_record(record)
    return db
Exemplo n.º 5
0
def epics_database():
    df = DatabaseFile(file_name=SIMPLE_DATABASE)
    db = EpicsDatabase()
    for record in df.next_record():
        db.add_record(record)
    return db
Exemplo n.º 6
0
def grep_file(f, file_name, p_args):
    """
    This routine looks for matches in the record name, record type, field name and/or field value.
    The command line options are used to select what type of matching is desired.
    The output will have a valid database syntax.
    :param f: database file
    :param file_name: database file name
    :param p_args: command line arguments
    :type p_args: Namespace
    """

    # Print debug information
    if debug_flag:
        print(file_name, p_args.pattern, file_name)

    # This variable is used to control whether the file name should be printed embedded in the
    # output database as a comment. When no matches are found no file name should be printed not
    # be printed to avoid unwanted output.
    more_than_one_file = True if len(p_args.files) > 1 else False

    # The following variable controls whether only the file name should be printed when a match is found
    # Flags to control the output
    file_name_only = p_args.filename

    # This variable is usd to control whether all the fields in a matching record
    # should be printed when a match is found.
    all_fields = p_args.all_fields

    if debug_flag:
        print('more_than_one_file, file_name_only =', more_than_one_file, file_name_only)

    # Compile the pattern to make sure that there are no errors in it.
    # This will speed up searches and will catch errors before processing files.
    try:
        p = re.compile(p_args.pattern, re.IGNORECASE if p_args.ignorecase else 0)
    except Exception as ex:
        print('Error while parsing regular expression', ex)
        return

    # Create the database file object
    df = DatabaseFile(f)
    if debug_flag:
        print(df)

    # Match field name or value?
    match_fields = p_args.field_name or p_args.field_value

    # Used to break out from two nested loops (Python doesn't have labeled breaks yet).
    break_out = False

    # Loop over all records in the file.
    # The records will be processed in the same order as in the file.
    for record in df.next_record():
        assert (isinstance(record, EpicsRecord))

        # This variable is used to determine whether the start of a record was printed or not.
        # We only need the record name once per record. A match in a field name or value will
        # print the record start if it was not printed already.
        record_start_printed = False

        # Get record and type
        record_name, record_type = record.get_name(), record.get_type()
        if debug_flag:
            print(record_name, record_type)

        # Check whether matching for record name and type is selected
        # Print the record header if there's a record match
        if (p_args.record_name and p.search(record_name)) or (p_args.record_type and p.search(record_type)):

            # Print the file name and stop looking for more matches
            if file_name_only:
                print(file_name)
                break

            # Print a file header as comment if there are more than one input files
            if more_than_one_file:
                print(file_name_header(file_name))
                more_than_one_file = False  # file name header was printed

            # Print the record start and mark it as printed
            print(format_record_start(record_name, record_type))
            record_start_printed = True  # record start was printed

            # If printing all fields then don't bother checking for matching fields
            if all_fields:
                print_all_fields(record)
                print(format_record_end())
                continue

        # Match fields?
        if match_fields:
            for field_name, field_value in record.get_fields():

                # Check matching for field name and/or value
                if (p_args.field_name and p.search(field_name)) or (p_args.field_value and p.search(field_value)):

                    # Print the file name and stop looking for more matches
                    if file_name_only:
                        print(file_name)
                        break_out = True  # stop record loop
                        break

                    # The record start and file header should be printed if it was done already.
                    if not record_start_printed:
                        if more_than_one_file:
                            print(file_name_header(file_name))
                            more_than_one_file = False  # file name was printed
                        print(format_record_start(record_name, record_type))
                        record_start_printed = True  # record start was printed

                    # If printing all fields then break the loop and continue with the next record
                    if all_fields:
                        print_all_fields(record)
                        break
                    else:
                        print(format_field(field_name, field_value))

            # Break out from the record loop
            if break_out:
                break

        # Print the record end if the start was printed
        if record_start_printed:
            print(format_record_end())

    df.close()

    return