Esempio n. 1
0
def create_index_file(index_file_name, database_list):
    """
    Write the index (list of records) for a given system to a disk file.
    :param index_file_name: index file name
    :type index_file_name: str
    :param database_list: list of databases for the given system
    :type database_list: list
    :return:
    """
    record_name_list = []
    for database_name in database_list:
        print(database_name)

        # Open database and macro substitution file (if any)
        db = DatabaseFile(file_name=database_name)
        m = read_subs_file(database_name)

        # Create a list with all records in the databases
        record_name_list.extend([r[0] for r in db.next_record_name()])
        # print record_name_list

        # Substitute macros if the macro substitution file was defined.
        # There's no need to replace macros in the record fields since
        # only record names are written to the index files.
        if m is not None:
            record_name_list = [m.replace_macros(r) for r in record_name_list]

    # Write the index file
    f = open(index_file_name, 'w')
    f.write("\n".join(str(x.strip()) for x in record_name_list))
    f.close()
Esempio n. 2
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
Esempio n. 3
0
def test_constructor(file_object):
    try:
        DatabaseFile()
    except FileNotFoundError:
        pass
    try:
        DatabaseFile(file_name='inexistent.db')
    except FileNotFoundError:
        pass
    DatabaseFile(file_object)
    DatabaseFile(f_in=file_object)
Esempio n. 4
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
Esempio n. 5
0
def diff_files_internal(file_name1, file_name2, p_args):
    """
    Open the two database files and call the the internal difference function
    :param file_name1: file name 1
    :type file_name1: str
    :param file_name2: file name 2
    :type file_name2: str
    :param p_args: command line arguments
    :type p_args: Namespace
    :return:
    """
    if debug_flag:
        print('\n-- diff_databases', file_name1, file_name2)
    try:
        # f1 = open(file1, 'r')
        # f2 = open(file2, 'r')
        # diff_databases(f1, f2, file1, file2)
        my_filter = diff_filter if p_args.clean else None
        df1 = DatabaseFile(file_name=file_name1, filter_function=my_filter)
        df2 = DatabaseFile(file_name=file_name2, filter_function=my_filter)
        diff_databases(df1, df2, file_name1, file_name2)
        df1.close()
        df2.close()
    except (OSError, IOError) as ex:
        print(ex)
Esempio n. 6
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
Esempio n. 7
0
def database_file():
    """
    Fixture used to return a valid DatabaseFile object
    :return: database file
    :rtype: DatabaseFile
    """
    return DatabaseFile(file_name=SIMPLE_DATABASE)
Esempio n. 8
0
def sort_database(f, file_name, p_args):
    """
    This is the callback function for process_file_list.
    Read the database file and print the database sorted by record and field names.
    :param f: database file
    :type f: TextIOBase
    :param file_name: file name (needed, but not used)
    :type file_name: str
    :param p_args: command line arguments (not used)
    :type p_args: Namespace
    :return: None
    """
    if debug_flag:
        print('\n-- sort_database', f, file_name, p_args)
    df = DatabaseFile(f)
    db = df.read_database()
    assert (isinstance(db, EpicsDatabase))
    db.write_sorted_database(reverse=p_args.reverse)
    df.close()
    return
Esempio n. 9
0
def list_records(f, file_name, p_args):
    """
    This is the callback function for process_file_list.
    It will get called once for each file in the input file list.
    List records in a database file.
    :param f: database file
    :param file_name: file name (not used)
    :param p_args: command line arguments
    :return: None
    """
    if debug_flag:
        print('\n--list_records', f, file_name, p_args)
    df = DatabaseFile(f)
    for record_name, record_type in df.next_record_name():
        if p_args.type:
            print(record_name + ', ' + record_type)
        else:
            print(record_name)
    df.close()
    return
Esempio n. 10
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
Esempio n. 11
0
def epics_database():
    df = DatabaseFile(file_name=SIMPLE_DATABASE)
    db = EpicsDatabase()
    for record in df.next_record():
        db.add_record(record)
    return db
Esempio n. 12
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
Esempio n. 13
0
def diff_files_external(file_name1, file_name2, p_args):
    """
    Open the two database files, sort them and call the external difference program.
    :param file_name1: file name 1
    :param file_name2: file name 2
    :param p_args: command line arguments
    :return: None
    """
    # Read databases into memory
    try:
        my_filter = diff_filter if p_args.clean else None
        df1 = DatabaseFile(file_name=file_name1, filter_function=my_filter)
        df2 = DatabaseFile(file_name=file_name2, filter_function=my_filter)
        db1 = df1.read_database()
        db2 = df2.read_database()
        df1.close()
        df2.close()
    except (OSError, IOError) as ex:
        print(ex)
        return

    # Create output file names by appending a time stamp
    time_stamp = str(int(time.time()))
    output_file_name1 = os.path.join(
        TEMP_DIRECTORY,
        os.path.basename(file_name1) + '_' + time_stamp + '_1')
    output_file_name2 = os.path.join(
        TEMP_DIRECTORY,
        os.path.basename(file_name2) + '_' + time_stamp + '_2')

    # Write the sorted databases to disk
    for db, file_name in [(db1, output_file_name1), (db2, output_file_name2)]:
        # print db, file_name
        assert (isinstance(db, EpicsDatabase))
        try:
            f = open(file_name, 'w')
            db.write_sorted_database(f_out=f)
            f.close()
        except (OSError, IOError) as ex:
            print(ex)
            return

    # Call external program to diff the files
    external_program = p_args.program[0]
    print('calling', external_program, 'with', output_file_name1, 'and',
          output_file_name2)
    try:
        subprocess.call(
            [external_program, output_file_name1, output_file_name2])
    except subprocess.CalledProcessError as ex:
        print('error while calling' + external_program)
        print(ex)

    # Remove temporary files
    try:
        os.remove(output_file_name1)
        os.remove(output_file_name2)
    except OSError as ex:
        print(ex)

    return