<commit_before>""" This module contains the functionality for running and compiling C functions """

from collections import namedtuple
import subprocess
import platform
import errno
import re
import logging
import ctypes as C
import _ctypes

import numpy
import numpy.ctypeslib

from kernel_tuner.util import get_temp_filename, delete_temp_file, write_file

dtype_map = {"int8": C.c_int8,
             "int16": C.c_int16,
             "int32": C.c_int32,
             "int64": C.c_int64,
             "uint8": C.c_uint8,
             "uint16": C.c_uint16,
             "uint32": C.c_uint32,
             "uint64": C.c_uint64,
             "float32": C.c_float,
             "float64": C.c_double}

# This represents an individual kernel argument.
# It contains a numpy object (ndarray or number) and a ctypes object with a copy
# of the argument data. For an ndarray, the ctypes object is a wrapper for the ndarray's data.
Argument = namedtuple("Argument", ["numpy", "ctypes"])

class CFunctions(object):
    """Class that groups the code for running and compiling C functions"""

    def __init__(self, iterations=7, compiler_options=None, compiler=None):
        """instantiate CFunctions object used for interacting with C code

        :param iterations: Number of iterations used while benchmarking a kernel, 7 by default.
        :type iterations: int
        """
        self.iterations = iterations
        self.max_threads = 1024
        self.compiler_options = compiler_options
        self.compiler = compiler or "g++"  # use gcc by default
        self.lib = None
        self.using_openmp = False

        try:
            cc_version = str(subprocess.check_output([self.compiler, "--version"]))
            cc_version = cc_version.splitlines()[0].split(" ")[-1]
        except OSError as e:
            raise e

        #check if nvcc is available
        self.nvcc_available = False
        try:
            nvcc_version = str(subprocess.check_output(["nvcc", "--version"]))
            nvcc_version = nvcc_version.splitlines()[-1].split(" ")[-1]
            self.nvcc_available = True
        except OSError as e:
            if e.errno != errno.ENOENT:
                raise e

        #environment info
        env = dict()
        env["CC Version"] = cc_version
        if self.nvcc_available:
            env["NVCC Version"] = nvcc_version
        env["iterations"] = self.iterations
        env["compiler_options"] = compiler_options
        self.env = env
        self.name = platform.processor()

    def ready_argument_list(self, arguments):
        """ready argument list to be passed to the C function

        :param arguments: List of arguments to be passed to the C function.
            The order should match the argument list on the C function.
            Allowed values are numpy.ndarray, and/or numpy.int32, numpy.float32, and so on.
        :type arguments: list(numpy objects)

        :returns: A list of arguments that can be passed to the C function.
        :rtype: list(Argument)
        """
        ctype_args = [ None for _ in arguments]

        for i, arg in enumerate(arguments):
            if not isinstance(arg, (numpy.ndarray, numpy.number)):
                raise TypeError("Argument is not numpy ndarray or numpy scalar %s" % type(arg))
            dtype_str = str(arg.dtype)
            #data = arg.copy()
            if isinstance(arg, numpy.ndarray):
                if dtype_str in dtype_map.keys():
                    # In numpy <= 1.15, ndarray.ctypes.data_as does not itself keep a reference
                    # to its underlying array, so we need to store a reference to arg.copy()
                    # in the Argument object manually to avoid it being deleted.
                    # (This changed in numpy > 1.15.)
                    #data_ctypes = data.ctypes.data_as(C.POINTER(dtype_map[dtype_str]))
                    data_ctypes = arg.ctypes.data_as(C.POINTER(dtype_map[dtype_str]))
                else:
                    raise TypeError("unknown dtype for ndarray")
            elif isinstance(arg, numpy.generic):
                data_ctypes = dtype_map[dtype_str](arg)
            #ctype_args[i] = Argument(numpy=data, ctypes=data_ctypes)
            ctype_args[i] = Argument(numpy=arg, ctypes=data_ctypes)
        return ctype_args

    def compile(self, kernel_instance):
        """call the C compiler to compile the kernel, return the function

        :param kernel_name: The name of the kernel to be compiled, used to lookup the
            function after compilation.
        :type kernel_name: string

        :param kernel_string: The C code that contains the function `kernel_name`
        :type kernel_string: string

        :returns: An ctypes function that can be called directly.
        :rtype: ctypes._FuncPtr
        """
        logging.debug('compiling ' + kernel_instance.name)

        kernel_string = kernel_instance.kernel_string

        if self.lib != None:
            self.cleanup_lib()

        compiler_options = ["-fPIC"]

        #detect openmp
        if "#include <omp.h>" in kernel_string or "use omp_lib" in kernel_string:
            logging.debug('set using_openmp to true')
            self.using_openmp = True
            if self.compiler == "pgfortran":
                compiler_options.append("-mp")
            else:
                compiler_options.append("-fopenmp")

        #if filename is known, use that one
        suffix = kernel_instance.kernel_source.get_user_suffix()

        #if code contains device code, suffix .cu is required
        device_code_signals = ["__global", "__syncthreads()", "threadIdx"]
        if any([snippet in kernel_string for snippet in device_code_signals]):
            suffix = ".cu"

        #detect whether to use nvcc as default instead of g++, may overrule an explicitly passed g++
        if (suffix == ".cu") or ("#include <cuda" in kernel_string) or ("cudaMemcpy" in kernel_string):
            if self.compiler == "g++" and self.nvcc_available:
                self.compiler = "nvcc"

        if suffix is None:
            #select right suffix based on compiler
            suffix = ".cc"

            if self.compiler in ["gfortran", "pgfortran", "ftn", "ifort"]:
                suffix = ".F90"

        if self.compiler == "nvcc":
            compiler_options = ["-Xcompiler=" + c for c in compiler_options]

        #this basically checks if we aren't compiling Fortran
        #at the moment any C, C++, or CUDA code is assumed to use extern "C" linkage
        if ".c" in suffix:
            if not "extern \"C\"" in kernel_string:
                kernel_string = "extern \"C\" {\n" + kernel_string + "\n}"

        #copy user specified compiler options to current list
        if self.compiler_options:
            compiler_options += self.compiler_options

        lib_args = []
        if "CL/cl.h" in kernel_string:
            lib_args = ["-lOpenCL"]

        logging.debug('using compiler ' + self.compiler)
        logging.debug('compiler_options ' + " ".join(compiler_options))
        logging.debug('lib_args ' + " ".join(lib_args))

        source_file = get_temp_filename(suffix=suffix)
        filename = ".".join(source_file.split(".")[:-1])

        #detect Fortran modules
        match = re.search(r"\s*module\s+([a-zA-Z_]*)", kernel_string)
        if match:
            if self.compiler == "gfortran":
                kernel_name = "__" + match.group(1) + "_MOD_" + kernel_instance.name
            elif self.compiler in ["ftn", "ifort"]:
                kernel_name = match.group(1) + "_mp_" + kernel_instance.name + "_"
            elif self.compiler == "pgfortran":
                kernel_name = match.group(1) + "_" + kernel_instance.name + "_"

        try:
            write_file(source_file, kernel_string)

            lib_extension = ".so"
            if platform.system() == "Darwin":
                lib_extension = ".dylib"

            subprocess.check_call([self.compiler, "-c", source_file] + compiler_options + ["-o", filename + ".o"])
            subprocess.check_call([self.compiler, filename + ".o"] + compiler_options + ["-shared", "-o", filename + lib_extension] + lib_args)

            self.lib = numpy.ctypeslib.load_library(filename, '.')
            func = getattr(self.lib, kernel_instance.name)
            func.restype = C.c_float

        finally:
            delete_temp_file(source_file)
            delete_temp_file(filename+".o")
            delete_temp_file(filename+".so")
            delete_temp_file(filename+".dylib")

        return func

    def benchmark(self, func, c_args, threads, grid):
        """runs the kernel repeatedly, returns averaged returned value

        The C function tuning is a little bit more flexible than direct CUDA
        or OpenCL kernel tuning. The C function needs to measure time, or some
        other quality metric you wish to tune on, on its own and should
        therefore return a single floating-point value.

        Benchmark runs the C function repeatedly and returns the average of the
        values returned by the C function. The number of iterations is set
        during the creation of the CFunctions object. For all measurements the
        lowest and highest values are discarded and the rest is included in the
        average. The reason for this is to be robust against initialization
        artifacts and other exceptional cases.

        :param func: A C function compiled for this specific configuration
        :type func: ctypes._FuncPtr

        :param c_args: A list of arguments to the function, order should match the
            order in the code. The list should be prepared using
            ready_argument_list().
        :type c_args: list(Argument)

        :param threads: Ignored, but left as argument for now to have the same
            interface as CudaFunctions and OpenCLFunctions.
        :type threads: any

        :param grid: Ignored, but left as argument for now to have the same
            interface as CudaFunctions and OpenCLFunctions.
        :type grid: any

        :returns: All execution times.
        :rtype: dict()
        """
        result = dict()
        result["times"] = []
        for _ in range(self.iterations):
            value = self.run_kernel(func, c_args, threads, grid)

            #I would like to replace the following with actually capturing
            #stderr and detecting the error directly in Python, it proved
            #however that capturing stderr for non-Python functions from Python
            #is a rather difficult thing to do
            #
            #The current, less than ideal, scheme uses the convention that a
            #negative time indicates a 'too many resources requested for launch'
            #which Kernel Tuner can silently ignore
            if value < 0.0:
                raise Exception("too many resources requested for launch")

            result["times"].append(value)
        result["time"] = numpy.mean(result["times"])
        return result

    def run_kernel(self, func, c_args, threads, grid):
        """runs the kernel once, returns whatever the kernel returns

        :param func: A C function compiled for this specific configuration
        :type func: ctypes._FuncPtr

        :param c_args: A list of arguments to the function, order should match the
            order in the code. The list should be prepared using
            ready_argument_list().
        :type c_args: list(Argument)

        :param threads: Ignored, but left as argument for now to have the same
            interface as CudaFunctions and OpenCLFunctions.
        :type threads: any

        :param grid: Ignored, but left as argument for now to have the same
            interface as CudaFunctions and OpenCLFunctions.
        :type grid: any

        :returns: A robust average of values returned by the C function.
        :rtype: float
        """
        logging.debug("run_kernel")
        logging.debug("arguments=" + str([str(arg.ctypes) for arg in c_args]))

        time = func(*[arg.ctypes for arg in c_args])

        return time

    def memset(self, allocation, value, size):
        """set the memory in allocation to the value in value

        :param allocation: An Argument for some memory allocation unit
        :type allocation: Argument

        :param value: The value to set the memory to
        :type value: a single 8-bit unsigned int

        :param size: The size of to the allocation unit in bytes
        :type size: int
        """
        C.memset(allocation.ctypes, value, size)

    def memcpy_dtoh(self, dest, src):
        """a simple memcpy copying from an Argument to a numpy array

        :param dest: A numpy array to store the data
        :type dest: numpy.ndarray

        :param src: An Argument for some memory allocation
        :type src: Argument
        """
        dest[:] = src.numpy

    def memcpy_htod(self, dest, src):
        """a simple memcpy copying from a numpy array to an Argument

        :param dest: An Argument for some memory allocation
        :type dst: Argument

        :param src: A numpy array containing the source data
        :type src: numpy.ndarray
        """
        dest.numpy[:] = src

    def cleanup_lib(self):
        """ unload the previously loaded shared library """
        if not self.using_openmp:
            #this if statement is necessary because shared libraries that use
            #OpenMP will core dump when unloaded, this is a well-known issue with OpenMP
            logging.debug('unloading shared library')
            _ctypes.dlclose(self.lib._handle)

    units = {}
<commit_msg>bugfix fortran support #108<commit_after>""" This module contains the functionality for running and compiling C functions """

from collections import namedtuple
import subprocess
import platform
import errno
import re
import logging
import ctypes as C
import _ctypes

import numpy
import numpy.ctypeslib

from kernel_tuner.util import get_temp_filename, delete_temp_file, write_file

dtype_map = {"int8": C.c_int8,
             "int16": C.c_int16,
             "int32": C.c_int32,
             "int64": C.c_int64,
             "uint8": C.c_uint8,
             "uint16": C.c_uint16,
             "uint32": C.c_uint32,
             "uint64": C.c_uint64,
             "float32": C.c_float,
             "float64": C.c_double}

# This represents an individual kernel argument.
# It contains a numpy object (ndarray or number) and a ctypes object with a copy
# of the argument data. For an ndarray, the ctypes object is a wrapper for the ndarray's data.
Argument = namedtuple("Argument", ["numpy", "ctypes"])

class CFunctions(object):
    """Class that groups the code for running and compiling C functions"""

    def __init__(self, iterations=7, compiler_options=None, compiler=None):
        """instantiate CFunctions object used for interacting with C code

        :param iterations: Number of iterations used while benchmarking a kernel, 7 by default.
        :type iterations: int
        """
        self.iterations = iterations
        self.max_threads = 1024
        self.compiler_options = compiler_options
        self.compiler = compiler or "g++"  # use gcc by default
        self.lib = None
        self.using_openmp = False

        try:
            cc_version = str(subprocess.check_output([self.compiler, "--version"]))
            cc_version = cc_version.splitlines()[0].split(" ")[-1]
        except OSError as e:
            raise e

        #check if nvcc is available
        self.nvcc_available = False
        try:
            nvcc_version = str(subprocess.check_output(["nvcc", "--version"]))
            nvcc_version = nvcc_version.splitlines()[-1].split(" ")[-1]
            self.nvcc_available = True
        except OSError as e:
            if e.errno != errno.ENOENT:
                raise e

        #environment info
        env = dict()
        env["CC Version"] = cc_version
        if self.nvcc_available:
            env["NVCC Version"] = nvcc_version
        env["iterations"] = self.iterations
        env["compiler_options"] = compiler_options
        self.env = env
        self.name = platform.processor()

    def ready_argument_list(self, arguments):
        """ready argument list to be passed to the C function

        :param arguments: List of arguments to be passed to the C function.
            The order should match the argument list on the C function.
            Allowed values are numpy.ndarray, and/or numpy.int32, numpy.float32, and so on.
        :type arguments: list(numpy objects)

        :returns: A list of arguments that can be passed to the C function.
        :rtype: list(Argument)
        """
        ctype_args = [ None for _ in arguments]

        for i, arg in enumerate(arguments):
            if not isinstance(arg, (numpy.ndarray, numpy.number)):
                raise TypeError("Argument is not numpy ndarray or numpy scalar %s" % type(arg))
            dtype_str = str(arg.dtype)
            #data = arg.copy()
            if isinstance(arg, numpy.ndarray):
                if dtype_str in dtype_map.keys():
                    # In numpy <= 1.15, ndarray.ctypes.data_as does not itself keep a reference
                    # to its underlying array, so we need to store a reference to arg.copy()
                    # in the Argument object manually to avoid it being deleted.
                    # (This changed in numpy > 1.15.)
                    #data_ctypes = data.ctypes.data_as(C.POINTER(dtype_map[dtype_str]))
                    data_ctypes = arg.ctypes.data_as(C.POINTER(dtype_map[dtype_str]))
                else:
                    raise TypeError("unknown dtype for ndarray")
            elif isinstance(arg, numpy.generic):
                data_ctypes = dtype_map[dtype_str](arg)
            #ctype_args[i] = Argument(numpy=data, ctypes=data_ctypes)
            ctype_args[i] = Argument(numpy=arg, ctypes=data_ctypes)
        return ctype_args

    def compile(self, kernel_instance):
        """call the C compiler to compile the kernel, return the function

        :param kernel_instance: An object representing the specific instance of the tunable kernel
            in the parameter space.
        :type kernel_instance: kernel_tuner.core.KernelInstance

        :returns: An ctypes function that can be called directly.
        :rtype: ctypes._FuncPtr
        """
        logging.debug('compiling ' + kernel_instance.name)

        kernel_string = kernel_instance.kernel_string
        kernel_name = kernel_instance.name

        if self.lib != None:
            self.cleanup_lib()

        compiler_options = ["-fPIC"]

        #detect openmp
        if "#include <omp.h>" in kernel_string or "use omp_lib" in kernel_string:
            logging.debug('set using_openmp to true')
            self.using_openmp = True
            if self.compiler == "pgfortran":
                compiler_options.append("-mp")
            else:
                compiler_options.append("-fopenmp")

        #if filename is known, use that one
        suffix = kernel_instance.kernel_source.get_user_suffix()

        #if code contains device code, suffix .cu is required
        device_code_signals = ["__global", "__syncthreads()", "threadIdx"]
        if any([snippet in kernel_string for snippet in device_code_signals]):
            suffix = ".cu"

        #detect whether to use nvcc as default instead of g++, may overrule an explicitly passed g++
        if (suffix == ".cu") or ("#include <cuda" in kernel_string) or ("cudaMemcpy" in kernel_string):
            if self.compiler == "g++" and self.nvcc_available:
                self.compiler = "nvcc"

        if suffix is None:
            #select right suffix based on compiler
            suffix = ".cc"

            if self.compiler in ["gfortran", "pgfortran", "ftn", "ifort"]:
                suffix = ".F90"

        if self.compiler == "nvcc":
            compiler_options = ["-Xcompiler=" + c for c in compiler_options]

        #this basically checks if we aren't compiling Fortran
        #at the moment any C, C++, or CUDA code is assumed to use extern "C" linkage
        if ".c" in suffix:
            if not "extern \"C\"" in kernel_string:
                kernel_string = "extern \"C\" {\n" + kernel_string + "\n}"

        #copy user specified compiler options to current list
        if self.compiler_options:
            compiler_options += self.compiler_options

        lib_args = []
        if "CL/cl.h" in kernel_string:
            lib_args = ["-lOpenCL"]

        logging.debug('using compiler ' + self.compiler)
        logging.debug('compiler_options ' + " ".join(compiler_options))
        logging.debug('lib_args ' + " ".join(lib_args))

        source_file = get_temp_filename(suffix=suffix)
        filename = ".".join(source_file.split(".")[:-1])

        #detect Fortran modules
        match = re.search(r"\s*module\s+([a-zA-Z_]*)", kernel_string)
        if match:
            if self.compiler == "gfortran":
                kernel_name = "__" + match.group(1) + "_MOD_" + kernel_name
            elif self.compiler in ["ftn", "ifort"]:
                kernel_name = match.group(1) + "_mp_" + kernel_name + "_"
            elif self.compiler == "pgfortran":
                kernel_name = match.group(1) + "_" + kernel_name + "_"

        try:
            write_file(source_file, kernel_string)

            lib_extension = ".so"
            if platform.system() == "Darwin":
                lib_extension = ".dylib"

            subprocess.check_call([self.compiler, "-c", source_file] + compiler_options + ["-o", filename + ".o"])
            subprocess.check_call([self.compiler, filename + ".o"] + compiler_options + ["-shared", "-o", filename + lib_extension] + lib_args)

            self.lib = numpy.ctypeslib.load_library(filename, '.')
            func = getattr(self.lib, kernel_name)
            func.restype = C.c_float

        finally:
            delete_temp_file(source_file)
            delete_temp_file(filename+".o")
            delete_temp_file(filename+".so")
            delete_temp_file(filename+".dylib")

        return func

    def benchmark(self, func, c_args, threads, grid):
        """runs the kernel repeatedly, returns averaged returned value

        The C function tuning is a little bit more flexible than direct CUDA
        or OpenCL kernel tuning. The C function needs to measure time, or some
        other quality metric you wish to tune on, on its own and should
        therefore return a single floating-point value.

        Benchmark runs the C function repeatedly and returns the average of the
        values returned by the C function. The number of iterations is set
        during the creation of the CFunctions object. For all measurements the
        lowest and highest values are discarded and the rest is included in the
        average. The reason for this is to be robust against initialization
        artifacts and other exceptional cases.

        :param func: A C function compiled for this specific configuration
        :type func: ctypes._FuncPtr

        :param c_args: A list of arguments to the function, order should match the
            order in the code. The list should be prepared using
            ready_argument_list().
        :type c_args: list(Argument)

        :param threads: Ignored, but left as argument for now to have the same
            interface as CudaFunctions and OpenCLFunctions.
        :type threads: any

        :param grid: Ignored, but left as argument for now to have the same
            interface as CudaFunctions and OpenCLFunctions.
        :type grid: any

        :returns: All execution times.
        :rtype: dict()
        """
        result = dict()
        result["times"] = []
        for _ in range(self.iterations):
            value = self.run_kernel(func, c_args, threads, grid)

            #I would like to replace the following with actually capturing
            #stderr and detecting the error directly in Python, it proved
            #however that capturing stderr for non-Python functions from Python
            #is a rather difficult thing to do
            #
            #The current, less than ideal, scheme uses the convention that a
            #negative time indicates a 'too many resources requested for launch'
            #which Kernel Tuner can silently ignore
            if value < 0.0:
                raise Exception("too many resources requested for launch")

            result["times"].append(value)
        result["time"] = numpy.mean(result["times"])
        return result

    def run_kernel(self, func, c_args, threads, grid):
        """runs the kernel once, returns whatever the kernel returns

        :param func: A C function compiled for this specific configuration
        :type func: ctypes._FuncPtr

        :param c_args: A list of arguments to the function, order should match the
            order in the code. The list should be prepared using
            ready_argument_list().
        :type c_args: list(Argument)

        :param threads: Ignored, but left as argument for now to have the same
            interface as CudaFunctions and OpenCLFunctions.
        :type threads: any

        :param grid: Ignored, but left as argument for now to have the same
            interface as CudaFunctions and OpenCLFunctions.
        :type grid: any

        :returns: A robust average of values returned by the C function.
        :rtype: float
        """
        logging.debug("run_kernel")
        logging.debug("arguments=" + str([str(arg.ctypes) for arg in c_args]))

        time = func(*[arg.ctypes for arg in c_args])

        return time

    def memset(self, allocation, value, size):
        """set the memory in allocation to the value in value

        :param allocation: An Argument for some memory allocation unit
        :type allocation: Argument

        :param value: The value to set the memory to
        :type value: a single 8-bit unsigned int

        :param size: The size of to the allocation unit in bytes
        :type size: int
        """
        C.memset(allocation.ctypes, value, size)

    def memcpy_dtoh(self, dest, src):
        """a simple memcpy copying from an Argument to a numpy array

        :param dest: A numpy array to store the data
        :type dest: numpy.ndarray

        :param src: An Argument for some memory allocation
        :type src: Argument
        """
        dest[:] = src.numpy

    def memcpy_htod(self, dest, src):
        """a simple memcpy copying from a numpy array to an Argument

        :param dest: An Argument for some memory allocation
        :type dst: Argument

        :param src: A numpy array containing the source data
        :type src: numpy.ndarray
        """
        dest.numpy[:] = src

    def cleanup_lib(self):
        """ unload the previously loaded shared library """
        if not self.using_openmp:
            #this if statement is necessary because shared libraries that use
            #OpenMP will core dump when unloaded, this is a well-known issue with OpenMP
            logging.debug('unloading shared library')
            _ctypes.dlclose(self.lib._handle)

    units = {}
<|endoftext|>


<commit_before>#!/usr/bin/env python3

"""
Keyboard layout generator.

Usage:
    layout.py <rows> <columns> <keycodefile> <layoutfile> [--filter=<tag>] [--reverse] [--checkkeycodes]
    layout.py (-h | --help)
    layout.py --version

Options:
    -h --help       Show this screen.
    --version       Show version.
    --reverse       Reverse the columns for all layers (useful for upside-down PCBs)
    --filter=<tag>  Include only layout sections matching <tag>

"""

#   Copyright 2016 Daniel P. Seemuth
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.

import collections
import docopt
import sys

__version__ = '0.1.0'

__title__ = 'keyboardlayout'
__author__ = 'Daniel P. Seemuth'
__description__ = 'Keyboard layout generator for keyboards from uniquekeyboard.com'
__license__ = 'Apache 2.0'
__copyright__ = 'Copyright 2016 Daniel P. Seemuth'

class KeyType:
    NORMAL = 0
    FN = 1
    SPACEFN = 2
    SWITCHLAYER = 3
    MEDIA = 4
    TOGGLEFN = 5

class Key:
    """One key's assignment: value and type.

    """

    def __init__(self, keyval, keytype=KeyType.NORMAL):
        self.keyval = keyval
        self.keytype = keytype

    def __repr__(self):
        return 'Key({:}, {:})'.format(self.keyval, self.keytype)

class Layer:
    """Hold all key assignments for one layer.

    """

    def __init__(self, size, keys=None):
        self.rows, self.columns = size
        self.keys = [
            [None for c in range(self.columns)]
            for r in range(self.rows)
        ]

        if keys:
            for coords, key in keys:
                x, y = coords
                self.keys[y][x] = key

    def commands(self, z):
        """Yield one uniqueksetkey command per key in the layout.

        """

        for r in range(self.rows):
            for c in range(self.columns):
                key = self.keys[r][c]

                if key is None:
                    key = Key(0, KeyType.NORMAL)

                yield 'uniqueksetkey({:}({:}({:}({:}({:}'.format(
                    c, r, z, key.keyval, key.keytype,
                )

def keycodesfromfile(file):
    ret = dict()

    for line in file:
        line = line.rstrip()

        if not line:
            continue

        try:
            name, keyval, keytype = line.split('\t')
        except ValueError:
            print('Invalid line:', line)
            continue

        keyval = int(keyval)
        keytype = int(keytype)

        ret[name] = Key(keyval, keytype)

    return ret

def layoutfromfile(file, layersize, filter, reverse, keycodes):
    unknowncodes = set()
    layers = dict()
    curlayer = None

    for linenum, line in enumerate(file, start=1):
        line = line.rstrip()

        if not line:
            continue

        if line.upper().startswith('LAYOUT '):
            parts = line.split()
            if len(parts) < 3:
                raise ValueError(
                    'invalid layer format',
                    linenum,
                    line,
                )

            layernum = int(parts[1])
            tag = parts[2]

            if (filter is None) or (tag == filter):
                if layernum in layers:
                    raise ValueError(
                        'layer already defined',
                        linenum,
                        layernum,
                    )

                curlayer = Layer(layersize)
                layers[layernum] = curlayer
                row = 0

            else:
                curlayer = None

            continue

        if curlayer is None:
            continue

        if row >= layersize[0]:
            raise ValueError(
                'too many rows',
                linenum,
                row,
            )

        parts = line.split('\t')

        for col, keyname in enumerate(parts):
            if not keyname:
                continue

            key = None
            if keyname in keycodes:
                key = keycodes[keyname]

            elif keyname.startswith('CUSTOM_'):
                subparts = keyname.split('_')
                if len(subparts) != 3:
                    raise ValueError(
                        'invalid CUSTOM key format',
                        linenum,
                        keyname,
                    )

                key = Key(
                    int(subparts[1]),
                    int(subparts[2]),
                )

            if key is not None:
                if reverse:
                    col = layersize[1] - 1 - col
                curlayer.keys[row][col] = key
            else:
                unknowncodes.add(keyname)

        row += 1

    return layers, unknowncodes

if __name__ == '__main__':
    args = docopt.docopt(__doc__, version=__version__)

    with open(args['<keycodefile>'], 'r') as F:
        keycodes = keycodesfromfile(F)

    if args['--checkkeycodes']:
        val2names = collections.defaultdict(set)
        for name, key in keycodes.items():
            val2names[(key.keyval, key.keytype)].add(name)

        for key, names in val2names.items():
            if len(names) != 1:
                print('KEY2CODE', key, sorted(names))

        sys.exit(0)

    rows = int(args['<rows>'])
    columns = int(args['<columns>'])

    with open(args['<layoutfile>'], 'r') as F:
        layers, unknowncodes = layoutfromfile(
            F,
            (rows, columns),
            args['--filter'],
            args['--reverse'],
            keycodes,
        )

    for layernum, layer in sorted(layers.items()):
        for command in layer.commands(layernum):
            print(command, end=' ')
        print()

    for code in sorted(unknowncodes):
        print('UNKNOWN', repr(code))
<commit_msg>Add <command> argument for uniqueksetkey vs. uniqueksetsubkey<commit_after>#!/usr/bin/env python3

"""
Keyboard layout generator.

Usage:
    layout.py <rows> <columns> <keycodefile> <layoutfile> <command> [--filter=<tag>] [--reverse] [--checkkeycodes]
    layout.py (-h | --help)
    layout.py --version

Options:
    -h --help       Show this screen.
    --version       Show version.
    --reverse       Reverse the columns for all layers (useful for upside-down PCBs)
    --filter=<tag>  Include only layout sections matching <tag>

"""

#   Copyright 2016 Daniel P. Seemuth
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.

import collections
import docopt
import sys

__version__ = '0.1.0'

__title__ = 'keyboardlayout'
__author__ = 'Daniel P. Seemuth'
__description__ = 'Keyboard layout generator for keyboards from uniquekeyboard.com'
__license__ = 'Apache 2.0'
__copyright__ = 'Copyright 2016 Daniel P. Seemuth'

class KeyType:
    NORMAL = 0
    FN = 1
    SPACEFN = 2
    SWITCHLAYER = 3
    MEDIA = 4
    TOGGLEFN = 5

class Key:
    """One key's assignment: value and type.

    """

    def __init__(self, keyval, keytype=KeyType.NORMAL):
        self.keyval = keyval
        self.keytype = keytype

    def __repr__(self):
        return 'Key({:}, {:})'.format(self.keyval, self.keytype)

class Layer:
    """Hold all key assignments for one layer.

    """

    def __init__(self, size, keys=None):
        self.rows, self.columns = size
        self.keys = [
            [None for c in range(self.columns)]
            for r in range(self.rows)
        ]

        if keys:
            for coords, key in keys:
                x, y = coords
                self.keys[y][x] = key

    def commands(self, z):
        """Yield one uniqueksetkey command per key in the layout.

        """

        for r in range(self.rows):
            for c in range(self.columns):
                key = self.keys[r][c]

                if key is None:
                    key = Key(0, KeyType.NORMAL)

                yield '({:}({:}({:}({:}({:}'.format(
                    c, r, z, key.keyval, key.keytype,
                )

def keycodesfromfile(file):
    ret = dict()

    for line in file:
        line = line.rstrip()

        if not line:
            continue

        try:
            name, keyval, keytype = line.split('\t')
        except ValueError:
            print('Invalid line:', line)
            continue

        keyval = int(keyval)
        keytype = int(keytype)

        ret[name] = Key(keyval, keytype)

    return ret

def layoutfromfile(file, layersize, filter, reverse, keycodes):
    unknowncodes = set()
    layers = dict()
    curlayer = None

    for linenum, line in enumerate(file, start=1):
        line = line.rstrip()

        if not line:
            continue

        if line.upper().startswith('LAYOUT '):
            parts = line.split()
            if len(parts) < 3:
                raise ValueError(
                    'invalid layer format',
                    linenum,
                    line,
                )

            layernum = int(parts[1])
            tag = parts[2]

            if (filter is None) or (tag == filter):
                if layernum in layers:
                    raise ValueError(
                        'layer already defined',
                        linenum,
                        layernum,
                    )

                curlayer = Layer(layersize)
                layers[layernum] = curlayer
                row = 0

            else:
                curlayer = None

            continue

        if curlayer is None:
            continue

        if row >= layersize[0]:
            raise ValueError(
                'too many rows',
                linenum,
                row,
            )

        parts = line.split('\t')

        for col, keyname in enumerate(parts):
            if not keyname:
                continue

            key = None
            if keyname in keycodes:
                key = keycodes[keyname]

            elif keyname.startswith('CUSTOM_'):
                subparts = keyname.split('_')
                if len(subparts) != 3:
                    raise ValueError(
                        'invalid CUSTOM key format',
                        linenum,
                        keyname,
                    )

                key = Key(
                    int(subparts[1]),
                    int(subparts[2]),
                )

            if key is not None:
                if reverse:
                    col = layersize[1] - 1 - col
                curlayer.keys[row][col] = key
            else:
                unknowncodes.add(keyname)

        row += 1

    return layers, unknowncodes

if __name__ == '__main__':
    args = docopt.docopt(__doc__, version=__version__)

    with open(args['<keycodefile>'], 'r') as F:
        keycodes = keycodesfromfile(F)

    if args['--checkkeycodes']:
        val2names = collections.defaultdict(set)
        for name, key in keycodes.items():
            val2names[(key.keyval, key.keytype)].add(name)

        for key, names in val2names.items():
            if len(names) != 1:
                print('KEY2CODE', key, sorted(names))

        sys.exit(0)

    rows = int(args['<rows>'])
    columns = int(args['<columns>'])

    with open(args['<layoutfile>'], 'r') as F:
        layers, unknowncodes = layoutfromfile(
            F,
            (rows, columns),
            args['--filter'],
            args['--reverse'],
            keycodes,
        )

    for layernum, layer in sorted(layers.items()):
        for command in layer.commands(layernum):
            print(args['<command>'] + command, end=' ')
        print()

    for code in sorted(unknowncodes):
        print('UNKNOWN', repr(code))
<|endoftext|>


<commit_before>#
# Kiwi: a Framework and Enhanced Widgets for Python
#
# Copyright (C) 2006 Async Open Source
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
# USA
#
# Author(s): Johan Dahlin <jdahlin@async.com.br>
#            Ali Afshar <aafshar@gmail.com>

import sys

try:
    from zope.interface import implements, Attribute, Interface
    # pyflakes
    implements, Attribute, Interface
except ImportError:
    class Interface(object):
        def providedBy(cls, impl):
            for iface in getattr(impl, '__interfaces__', []):
                if issubclass(iface, cls):
                    return True
            return False

        providedBy = classmethod(providedBy)

    class Attribute(object):
        def __init__(self, __name__, __doc__=''):
            self.__name__=__name__
            self.__doc__=__doc__

    def implements(iface):
        frame = sys._getframe(1)
        try:
            frame.f_locals.setdefault('__interfaces__', []).append(iface)
        finally:
            del frame

class AlreadyImplementedError(Exception):
    """Called when a utility already exists."""

class _UtilityHandler(object):
    def __init__(self):
        self._utilities = {}

    def provide(self, iface, obj):
        global _interfaces
        if not issubclass(iface, Interface):
            raise TypeError(
                "iface must be an Interface subclass and not %r" % iface)

        if iface in self._utilities:
            raise AlreadyImplementedError("%s is already implemented" % iface)
        self._utilities[iface] = obj

    def get(self, iface):
        global _interfaces
        if not issubclass(iface, Interface):
            raise TypeError(
                "iface must be an Interface subclass and not %r" % iface)

        if not iface in self._utilities:
            raise NotImplementedError("No utility provided for %r" % iface)

        return self._utilities[iface]

def provide_utility(iface, utility):
    """
    Set the utility for the named interface. If the utility is already
    set, an {AlreadyImplementedError} is raised.

    @param iface: interface to set the utility for.
    @param utility: utility providing the interface.
    """
    global _handler
    _handler.provide(iface, utility)

def get_utility(iface):
    """
    Get the utility for the named interface. If the utility is not
    available (has not been set) a {NotImplementedError} is raised.

    @param iface: interface to retrieve the utility for.
    @type iface: utility providing the interface
    """

    global _handler
    return _handler.get(iface)

_handler = _UtilityHandler()

<commit_msg>Add replace argument to provide_utility<commit_after>#
# Kiwi: a Framework and Enhanced Widgets for Python
#
# Copyright (C) 2006 Async Open Source
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
# USA
#
# Author(s): Johan Dahlin <jdahlin@async.com.br>
#            Ali Afshar <aafshar@gmail.com>

import sys

try:
    from zope.interface import implements, Attribute, Interface
    # pyflakes
    implements, Attribute, Interface
except ImportError:
    class Interface(object):
        def providedBy(cls, impl):
            for iface in getattr(impl, '__interfaces__', []):
                if issubclass(iface, cls):
                    return True
            return False

        providedBy = classmethod(providedBy)

    class Attribute(object):
        def __init__(self, __name__, __doc__=''):
            self.__name__=__name__
            self.__doc__=__doc__

    def implements(iface):
        frame = sys._getframe(1)
        try:
            frame.f_locals.setdefault('__interfaces__', []).append(iface)
        finally:
            del frame

class AlreadyImplementedError(Exception):
    """Called when a utility already exists."""

class _UtilityHandler(object):
    def __init__(self):
        self._utilities = {}

    # FIXME: How to replace a utility properly
    def provide(self, iface, obj, replace=False):
        global _interfaces
        if not issubclass(iface, Interface):
            raise TypeError(
                "iface must be an Interface subclass and not %r" % iface)

        if not replace:
            if iface in self._utilities:
                raise AlreadyImplementedError("%s is already implemented" % iface)
        self._utilities[iface] = obj

    def get(self, iface):
        global _interfaces
        if not issubclass(iface, Interface):
            raise TypeError(
                "iface must be an Interface subclass and not %r" % iface)

        if not iface in self._utilities:
            raise NotImplementedError("No utility provided for %r" % iface)

        return self._utilities[iface]

def provide_utility(iface, utility, replace=False):
    """
    Set the utility for the named interface. If the utility is already
    set, an {AlreadyImplementedError} is raised.

    @param iface: interface to set the utility for.
    @param utility: utility providing the interface.
    """
    global _handler
    _handler.provide(iface, utility, replace)

def get_utility(iface):
    """
    Get the utility for the named interface. If the utility is not
    available (has not been set) a {NotImplementedError} is raised.

    @param iface: interface to retrieve the utility for.
    @type iface: utility providing the interface
    """

    global _handler
    return _handler.get(iface)

_handler = _UtilityHandler()

<|endoftext|>


<commit_before>#!/usr/bin/python
r"""
#############################################################
#    @file     openbmc_ffdc_list.py
#
#    @brief    List for FFDC ( First failure data capture )
#              commands and files to be collected as a part
#              of the test case failure.
#############################################################
"""

# -------------------
# FFDC default list
# -------------------

# -----------------------------------------------------------------
# Dict Name {  Index string : { Key String :  Comand string} }
# -----------------------------------------------------------------
# Add cmd's needed to be part of the ffdc report manifest file
FFDC_BMC_CMD = {
    'DRIVER INFO':
    {
        # String Name         Command
        'Build Info': 'cat /etc/version',
        'FW Level': 'cat /etc/os-release',
    },
    'BMC DATA':
    {
        'BMC OS': 'uname -a',
        'BMC Uptime': 'uptime',
        'BMC File System Disk Space Usage': 'df -hT',
    },
    'APPLICATION DATA':
    {
        'BMC state': '/usr/sbin/obmcutil  state',
    },
}

# Add file name and correcponding command needed for BMC
FFDC_BMC_FILE = {
    'BMC FILES':
    {
        # File Name         Command
        'BMC_proc_list': 'top -n 1 -b',
        'BMC_journalctl': 'journalctl --no-pager',
        'BMC_dmesg': 'dmesg',
        'BMC_procinfo': 'cat /proc/cpuinfo',
        'BMC_meminfo': 'cat /proc/meminfo',
    },
}

# Add file name and correcponding command needed for all Linux distributions
FFDC_OS_ALL_DISTROS_FILE = {
    'OS FILES':
    {
        # File Name         Command
        'OS_msglog': 'cat /sys/firmware/opal/msglog',
        'OS_cpufrequency': 'ppc64_cpu --frequency',
        'OS_dmesg': 'dmesg',
        'OS_boot': 'cat /var/log/boot.log',
        'OS_procinfo': 'cat /proc/cpuinfo',
        'OS_meminfo': 'cat /proc/meminfo',
        'OS_netstat': 'netstat -a',
    },
}

# Add file name and correcponding command needed for Ubuntu Linux
FFDC_OS_UBUNTU_FILE = {
    'OS FILES':
    {
        # File Name         Command
        'OS_isusb': 'lsusb -t ; lsusb -v',
        'OS_kern': 'tail -n 50000 /var/log/kern.log',
        'OS_authlog': 'cat /var/log/auth.log; cat /var/log/auth.log.1',
        'OS_syslog': 'tail -n 200000 /var/log/syslog',
        'OS_info': 'uname -a; dpkg -s opal-prd; dpkg -s ipmitool',
    },
}

# Add file name and correcponding command needed for RHEL Linux
FFDC_OS_RHEL_FILE = {
    'OS FILES':
    {
        # File Name         Command
        'OS_rsct': '/usr/bin/ctversion -bv',
        'OS_secure': 'cat /var/log/secure',
        'OS_syslog': 'tail -n 200000 /var/log/messages',
        'OS_info': 'lsb_release -a; cat /etc/redhat-release; uname -a; rpm -qa',
    },
}

# Add file name and correcponding command needed for RHEL Linux
FFDC_OS_IBM_POWERKVM_FILE = {
    'OS FILES':
    {
        # File Name         Command
        'OS_secure': 'cat /var/log/secure',
        'OS_syslog': 'tail -n 200000 /var/log/messages',
        'OS_info': 'lsb_release -a; uname -a; rpm -qa',
    },
}

# Enable when ready with openbmc/openbmc-test-automation#203
# replace with new path /xyz/openbmc_project
OPENBMC_BASE = '/org/openbmc/'
ENUMERATE_SENSORS = OPENBMC_BASE + 'sensors/enumerate'
ENUMERATE_SYSTEMS = OPENBMC_BASE + 'inventory/system/enumerate'
ENUMERATE_EVENTS = OPENBMC_BASE + 'records/events/enumerate'
ENUMERATE_LED = OPENBMC_BASE + 'control/led/enumerate'

# Add file name and correcponding Get Request
FFDC_GET_REQUEST = {
    'GET REQUESTS':
    {
        # File Name         Command
        'BMC_sensor_list': ENUMERATE_SENSORS,
        'BMC_inventory': ENUMERATE_SYSTEMS,
        'BMC_led': ENUMERATE_EVENTS,
        'BMC_record_log': ENUMERATE_LED,
    },
}

# Define your keywords in method/utils and call here
FFDC_METHOD_CALL = {
    'BMC LOGS':
    {
        # Description             Keyword name
        'FFDC Generic Report': 'BMC FFDC Manifest',
        'BMC Specific Files': 'BMC FFDC Files',
        'Get Request FFDC': 'BMC FFDC Get Requests',
        'OS FFDC': 'OS FFDC Files',
    },
}

# -----------------------------------------------------------------

# base class for FFDC default list
class openbmc_ffdc_list():

    def get_ffdc_bmc_cmd(self, i_type):
        r"""
        ########################################################################
        #   @brief    This method returns the list from the dictionary for cmds
        #   @param    i_type: @type string: string index lookup
        #   @return   List of key pair from the dictionary
        ########################################################################
        """
        return FFDC_BMC_CMD[i_type].items()

    def get_ffdc_bmc_file(self, i_type):
        r"""
        ########################################################################
        #   @brief    This method returns the list from the dictionary for scp
        #   @param    i_type: @type string: string index lookup
        #   @return   List of key pair from the dictionary
        ########################################################################
        """
        return FFDC_BMC_FILE[i_type].items()

    def get_ffdc_get_request(self, i_type):
        r"""
        ########################################################################
        #   @brief    This method returns the list from the dictionary for scp
        #   @param    i_type: @type string: string index lookup
        #   @return   List of key pair from the dictionary
        ########################################################################
        """
        return FFDC_GET_REQUEST[i_type].items()

    def get_ffdc_cmd_index(self):
        r"""
        ########################################################################
        #   @brief    This method returns the list index from dictionary
        #   @return   List of index to the dictionary
        ########################################################################
        """
        return FFDC_BMC_CMD.keys()

    def get_ffdc_get_request_index(self):
        r"""
        ########################################################################
        #   @brief    This method returns the list index from dictionary
        #   @return   List of index to the dictionary
        ########################################################################
        """
        return FFDC_GET_REQUEST.keys()

    def get_ffdc_file_index(self):
        r"""
        ########################################################################
        #   @brief    This method returns the list index from dictionary
        #   @return   List of index to the dictionary
        ########################################################################
        """
        return FFDC_BMC_FILE.keys()

    def get_ffdc_method_index(self):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   Index of the method dictionary
        ########################################################################
        """
        return FFDC_METHOD_CALL.keys()

    def get_ffdc_method_call(self, i_type):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   List of key pair keywords
        ########################################################################
        """
        return FFDC_METHOD_CALL[i_type].items()

    def get_ffdc_os_all_distros_index(self):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   Index of the method dictionary
        ########################################################################
        """
        return FFDC_OS_ALL_DISTROS_FILE.keys()

    def get_ffdc_os_all_distros_call(self, i_type):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   List of key pair keywords
        ########################################################################
        """
        return FFDC_OS_ALL_DISTROS_FILE[i_type].items()

    def get_ffdc_os_distro_index(self, distro):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   Index of the method dictionary
        ########################################################################
        """
        distro_file = "FFDC_OS_" + str(distro).upper() + "_FILE"
        return eval(distro_file).keys()

    def get_ffdc_os_distro_call(self, i_type, distro):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   List of key pair keywords
        ########################################################################
        """
        distro_file = "FFDC_OS_" + str(distro).upper() + "_FILE"
        return eval(distro_file)[i_type].items()

    def get_strip_string(self, i_str):
        r"""
        ########################################################################
        #   @brief    Returns the stripped strings
        #   @param    i_str: @type string: string name
        #   @return   Remove all special chars and return the string
        ########################################################################
        """
        return ''.join(e for e in i_str if e.isalnum())
<commit_msg>FFDC to capture new xyz Inventory<commit_after>#!/usr/bin/python
r"""
#############################################################
#    @file     openbmc_ffdc_list.py
#
#    @brief    List for FFDC ( First failure data capture )
#              commands and files to be collected as a part
#              of the test case failure.
#############################################################
"""

# -------------------
# FFDC default list
# -------------------

# -----------------------------------------------------------------
# Dict Name {  Index string : { Key String :  Comand string} }
# -----------------------------------------------------------------
# Add cmd's needed to be part of the ffdc report manifest file
FFDC_BMC_CMD = {
    'DRIVER INFO':
    {
        # String Name         Command
        'Build Info': 'cat /etc/version',
        'FW Level': 'cat /etc/os-release',
    },
    'BMC DATA':
    {
        'BMC OS': 'uname -a',
        'BMC Uptime': 'uptime',
        'BMC File System Disk Space Usage': 'df -hT',
    },
    'APPLICATION DATA':
    {
        'BMC state': '/usr/sbin/obmcutil  state',
    },
}

# Add file name and correcponding command needed for BMC
FFDC_BMC_FILE = {
    'BMC FILES':
    {
        # File Name         Command
        'BMC_proc_list': 'top -n 1 -b',
        'BMC_journalctl': 'journalctl --no-pager',
        'BMC_dmesg': 'dmesg',
        'BMC_procinfo': 'cat /proc/cpuinfo',
        'BMC_meminfo': 'cat /proc/meminfo',
    },
}

# Add file name and correcponding command needed for all Linux distributions
FFDC_OS_ALL_DISTROS_FILE = {
    'OS FILES':
    {
        # File Name         Command
        'OS_msglog': 'cat /sys/firmware/opal/msglog',
        'OS_cpufrequency': 'ppc64_cpu --frequency',
        'OS_dmesg': 'dmesg',
        'OS_boot': 'cat /var/log/boot.log',
        'OS_procinfo': 'cat /proc/cpuinfo',
        'OS_meminfo': 'cat /proc/meminfo',
        'OS_netstat': 'netstat -a',
    },
}

# Add file name and correcponding command needed for Ubuntu Linux
FFDC_OS_UBUNTU_FILE = {
    'OS FILES':
    {
        # File Name         Command
        'OS_isusb': 'lsusb -t ; lsusb -v',
        'OS_kern': 'tail -n 50000 /var/log/kern.log',
        'OS_authlog': 'cat /var/log/auth.log; cat /var/log/auth.log.1',
        'OS_syslog': 'tail -n 200000 /var/log/syslog',
        'OS_info': 'uname -a; dpkg -s opal-prd; dpkg -s ipmitool',
    },
}

# Add file name and correcponding command needed for RHEL Linux
FFDC_OS_RHEL_FILE = {
    'OS FILES':
    {
        # File Name         Command
        'OS_rsct': '/usr/bin/ctversion -bv',
        'OS_secure': 'cat /var/log/secure',
        'OS_syslog': 'tail -n 200000 /var/log/messages',
        'OS_info': 'lsb_release -a; cat /etc/redhat-release; uname -a; rpm -qa',
    },
}

# Add file name and correcponding command needed for RHEL Linux
FFDC_OS_IBM_POWERKVM_FILE = {
    'OS FILES':
    {
        # File Name         Command
        'OS_secure': 'cat /var/log/secure',
        'OS_syslog': 'tail -n 200000 /var/log/messages',
        'OS_info': 'lsb_release -a; uname -a; rpm -qa',
    },
}

# Enable when ready with openbmc/openbmc-test-automation#203
# replace with new path /xyz/openbmc_project
OPENBMC_BASE = '/org/openbmc/'
ENUMERATE_SENSORS = OPENBMC_BASE + 'sensors/enumerate'
# TODO: Use the xyz enums once moved to xyz completely
# ENUMERATE_SYSTEMS = OPENBMC_BASE + 'inventory/enumerate'
ENUMERATE_SYSTEMS = '/xyz/openbmc_project/Inventory/enumerate'
ENUMERATE_EVENTS = OPENBMC_BASE + 'records/events/enumerate'
ENUMERATE_LED = OPENBMC_BASE + 'control/led/enumerate'

# Add file name and correcponding Get Request
FFDC_GET_REQUEST = {
    'GET REQUESTS':
    {
        # File Name         Command
        'BMC_sensor_list': ENUMERATE_SENSORS,
        'BMC_inventory': ENUMERATE_SYSTEMS,
        'BMC_led': ENUMERATE_EVENTS,
        'BMC_record_log': ENUMERATE_LED,
    },
}

# Define your keywords in method/utils and call here
FFDC_METHOD_CALL = {
    'BMC LOGS':
    {
        # Description             Keyword name
        'FFDC Generic Report': 'BMC FFDC Manifest',
        'BMC Specific Files': 'BMC FFDC Files',
        'Get Request FFDC': 'BMC FFDC Get Requests',
        'OS FFDC': 'OS FFDC Files',
    },
}

# -----------------------------------------------------------------

# base class for FFDC default list
class openbmc_ffdc_list():

    def get_ffdc_bmc_cmd(self, i_type):
        r"""
        ########################################################################
        #   @brief    This method returns the list from the dictionary for cmds
        #   @param    i_type: @type string: string index lookup
        #   @return   List of key pair from the dictionary
        ########################################################################
        """
        return FFDC_BMC_CMD[i_type].items()

    def get_ffdc_bmc_file(self, i_type):
        r"""
        ########################################################################
        #   @brief    This method returns the list from the dictionary for scp
        #   @param    i_type: @type string: string index lookup
        #   @return   List of key pair from the dictionary
        ########################################################################
        """
        return FFDC_BMC_FILE[i_type].items()

    def get_ffdc_get_request(self, i_type):
        r"""
        ########################################################################
        #   @brief    This method returns the list from the dictionary for scp
        #   @param    i_type: @type string: string index lookup
        #   @return   List of key pair from the dictionary
        ########################################################################
        """
        return FFDC_GET_REQUEST[i_type].items()

    def get_ffdc_cmd_index(self):
        r"""
        ########################################################################
        #   @brief    This method returns the list index from dictionary
        #   @return   List of index to the dictionary
        ########################################################################
        """
        return FFDC_BMC_CMD.keys()

    def get_ffdc_get_request_index(self):
        r"""
        ########################################################################
        #   @brief    This method returns the list index from dictionary
        #   @return   List of index to the dictionary
        ########################################################################
        """
        return FFDC_GET_REQUEST.keys()

    def get_ffdc_file_index(self):
        r"""
        ########################################################################
        #   @brief    This method returns the list index from dictionary
        #   @return   List of index to the dictionary
        ########################################################################
        """
        return FFDC_BMC_FILE.keys()

    def get_ffdc_method_index(self):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   Index of the method dictionary
        ########################################################################
        """
        return FFDC_METHOD_CALL.keys()

    def get_ffdc_method_call(self, i_type):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   List of key pair keywords
        ########################################################################
        """
        return FFDC_METHOD_CALL[i_type].items()

    def get_ffdc_os_all_distros_index(self):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   Index of the method dictionary
        ########################################################################
        """
        return FFDC_OS_ALL_DISTROS_FILE.keys()

    def get_ffdc_os_all_distros_call(self, i_type):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   List of key pair keywords
        ########################################################################
        """
        return FFDC_OS_ALL_DISTROS_FILE[i_type].items()

    def get_ffdc_os_distro_index(self, distro):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   Index of the method dictionary
        ########################################################################
        """
        distro_file = "FFDC_OS_" + str(distro).upper() + "_FILE"
        return eval(distro_file).keys()

    def get_ffdc_os_distro_call(self, i_type, distro):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   List of key pair keywords
        ########################################################################
        """
        distro_file = "FFDC_OS_" + str(distro).upper() + "_FILE"
        return eval(distro_file)[i_type].items()

    def get_strip_string(self, i_str):
        r"""
        ########################################################################
        #   @brief    Returns the stripped strings
        #   @param    i_str: @type string: string name
        #   @return   Remove all special chars and return the string
        ########################################################################
        """
        return ''.join(e for e in i_str if e.isalnum())
<|endoftext|>


<commit_before>#!/usr/bin/python
r"""
#############################################################
#    @file     openbmc_ffdc_list.py
#
#    @brief    List for FFDC ( First failure data capture )
#              commands and files to be collected as a part
#              of the test case failure.
#############################################################
"""

# -------------------
# FFDC default list
# -------------------

# -----------------------------------------------------------------
# Dict Name {  Index string : { Key String :  Comand string} }
# -----------------------------------------------------------------
# Add cmd's needed to be part of the ffdc report manifest file
FFDC_BMC_CMD = {
    'DRIVER INFO':
    {
        # String Name         Command
        'FW Level': 'cat /etc/os-release',
    },
    'BMC DATA':
    {
        'BMC OS': 'uname -a',
        'BMC Uptime': 'uptime',
        'BMC File System Disk Space Usage': 'df -hT',
    },
    'APPLICATION DATA':
    {
        'BMC state': '/usr/sbin/obmcutil state',
    },
}

# Add file name and correcponding command needed for BMC
FFDC_BMC_FILE = {
    'BMC FILES':
    {
        # File Name         Command
        'BMC_proc_list': 'top -n 1 -b',
        'BMC_proc_fd_active_list': 'ls -Al /proc/*/fd/',
        'BMC_journalctl': 'journalctl --no-pager',
        'BMC_dmesg': 'dmesg',
        'BMC_procinfo': 'cat /proc/cpuinfo',
        'BMC_meminfo': 'cat /proc/meminfo',
    },
}

# Add file name and correcponding command needed for all Linux distributions
FFDC_OS_ALL_DISTROS_FILE = {
    'OS FILES':
    {
        # File Name         Command
        'OS_msglog': 'cat /sys/firmware/opal/msglog',
        'OS_cpufrequency': 'ppc64_cpu --frequency',
        'OS_dmesg': 'dmesg',
        'OS_boot': 'cat /var/log/boot.log',
        'OS_procinfo': 'cat /proc/cpuinfo',
        'OS_meminfo': 'cat /proc/meminfo',
        'OS_netstat': 'netstat -a',
        'OS_lspci': 'lspci',
        'OS_lscpu': 'lscpu',
        'OS_lscfg': 'lscfg',
    },
}

# Add file name and correcponding command needed for Ubuntu Linux
FFDC_OS_UBUNTU_FILE = {
    'OS FILES':
    {
        # File Name         Command
        'OS_isusb': 'lsusb -t ; lsusb -v',
        'OS_kern': 'tail -n 50000 /var/log/kern.log',
        'OS_authlog': 'cat /var/log/auth.log; cat /var/log/auth.log.1',
        'OS_syslog': 'tail -n 200000 /var/log/syslog',
        'OS_info': 'uname -a; dpkg -s opal-prd; dpkg -s ipmitool',
    },
}

# Add file name and correcponding command needed for RHEL Linux
FFDC_OS_RHEL_FILE = {
    'OS FILES':
    {
        # File Name         Command
        'OS_rsct': '/usr/bin/ctversion -bv',
        'OS_secure': 'cat /var/log/secure',
        'OS_syslog': 'tail -n 200000 /var/log/messages',
        'OS_info': 'lsb_release -a; cat /etc/redhat-release; uname -a; rpm -qa',
    },
}

# Add file name and correcponding command needed for RHEL Linux
FFDC_OS_IBM_POWERKVM_FILE = {
    'OS FILES':
    {
        # File Name         Command
        'OS_secure': 'cat /var/log/secure',
        'OS_syslog': 'tail -n 200000 /var/log/messages',
        'OS_info': 'lsb_release -a; uname -a; rpm -qa',
    },
}

# Enable when ready with openbmc/openbmc-test-automation#203
# replace with new path /xyz/openbmc_project
OPENBMC_BASE = '/org/openbmc/'
ENUMERATE_SENSORS = OPENBMC_BASE + 'sensors/enumerate'
# TODO: Use the xyz enums once moved to xyz completely
# ENUMERATE_SYSTEMS = OPENBMC_BASE + 'inventory/enumerate'
ENUMERATE_SYSTEMS = '/xyz/openbmc_project/inventory/enumerate'
ENUMERATE_ELOG = '/xyz/openbmc_project/logging/entry/enumerate'
ENUMERATE_EVENTS = OPENBMC_BASE + 'records/events/enumerate'
ENUMERATE_LED = OPENBMC_BASE + 'control/led/enumerate'

# Sensors/control data.
ENUMERATE_SENSOR = '/xyz/openbmc_project/sensors/enumerate'
ENUMERATE_CONTROL = '/xyz/openbmc_project/control/enumerate'

# Add file name and correcponding Get Request
FFDC_GET_REQUEST = {
    'GET REQUESTS':
    {
        # File Name         Command
        'BMC_sensor_list': ENUMERATE_SENSORS,
        'BMC_sensor_xyz_list': ENUMERATE_SENSOR,
        'BMC_control_list': ENUMERATE_CONTROL,
        'BMC_inventory': ENUMERATE_SYSTEMS,
        'BMC_elog': ENUMERATE_ELOG,
        'BMC_led': ENUMERATE_EVENTS,
        'BMC_record_log': ENUMERATE_LED,
    },
}

# Define your keywords in method/utils and call here
FFDC_METHOD_CALL = {
    'BMC LOGS':
    {
        # Description             Keyword name
        'FFDC Generic Report': 'BMC FFDC Manifest',
        'BMC Specific Files': 'BMC FFDC Files',
        'Get Request FFDC': 'BMC FFDC Get Requests',
        'OS FFDC': 'OS FFDC Files',
        'Core Files': 'SCP Coredump Files',
        'SEL Log': 'Collect eSEL Log',
    },
}

# -----------------------------------------------------------------

# base class for FFDC default list
class openbmc_ffdc_list():

    def get_ffdc_bmc_cmd(self, i_type):
        r"""
        ########################################################################
        #   @brief    This method returns the list from the dictionary for cmds
        #   @param    i_type: @type string: string index lookup
        #   @return   List of key pair from the dictionary
        ########################################################################
        """
        return FFDC_BMC_CMD[i_type].items()

    def get_ffdc_bmc_file(self, i_type):
        r"""
        ########################################################################
        #   @brief    This method returns the list from the dictionary for scp
        #   @param    i_type: @type string: string index lookup
        #   @return   List of key pair from the dictionary
        ########################################################################
        """
        return FFDC_BMC_FILE[i_type].items()

    def get_ffdc_get_request(self, i_type):
        r"""
        ########################################################################
        #   @brief    This method returns the list from the dictionary for scp
        #   @param    i_type: @type string: string index lookup
        #   @return   List of key pair from the dictionary
        ########################################################################
        """
        return FFDC_GET_REQUEST[i_type].items()

    def get_ffdc_cmd_index(self):
        r"""
        ########################################################################
        #   @brief    This method returns the list index from dictionary
        #   @return   List of index to the dictionary
        ########################################################################
        """
        return FFDC_BMC_CMD.keys()

    def get_ffdc_get_request_index(self):
        r"""
        ########################################################################
        #   @brief    This method returns the list index from dictionary
        #   @return   List of index to the dictionary
        ########################################################################
        """
        return FFDC_GET_REQUEST.keys()

    def get_ffdc_file_index(self):
        r"""
        ########################################################################
        #   @brief    This method returns the list index from dictionary
        #   @return   List of index to the dictionary
        ########################################################################
        """
        return FFDC_BMC_FILE.keys()

    def get_ffdc_method_index(self):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   Index of the method dictionary
        ########################################################################
        """
        return FFDC_METHOD_CALL.keys()

    def get_ffdc_method_desc(self,
                             index):
        r"""
        ########################################################################
        #   @brief   This method returns the just the keys from the dictionary.
        #   @return  List of ffdc descriptions.
        ########################################################################
        """
        return FFDC_METHOD_CALL[index].keys()

    def get_ffdc_method_call(self, i_type):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   List of key pair keywords
        ########################################################################
        """
        return FFDC_METHOD_CALL[i_type].items()

    def get_ffdc_os_all_distros_index(self):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   Index of the method dictionary
        ########################################################################
        """
        return FFDC_OS_ALL_DISTROS_FILE.keys()

    def get_ffdc_os_all_distros_call(self, i_type):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   List of key pair keywords
        ########################################################################
        """
        return FFDC_OS_ALL_DISTROS_FILE[i_type].items()

    def get_ffdc_os_distro_index(self, distro):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   Index of the method dictionary
        ########################################################################
        """
        distro_file = "FFDC_OS_" + str(distro).upper() + "_FILE"
        return eval(distro_file).keys()

    def get_ffdc_os_distro_call(self, i_type, distro):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   List of key pair keywords
        ########################################################################
        """
        distro_file = "FFDC_OS_" + str(distro).upper() + "_FILE"
        return eval(distro_file)[i_type].items()

    def get_strip_string(self, i_str):
        r"""
        ########################################################################
        #   @brief    Returns the stripped strings
        #   @param    i_str: @type string: string name
        #   @return   Remove all special chars and return the string
        ########################################################################
        """
        return ''.join(e for e in i_str if e.isalnum())

    def get_esel_index(self, esel_list):
        r"""
        #######################################################################
        #   @brief    Returns the eSEL binary index.
        #   @param    esel_ist: @type list: eSEL list.
        #   @return   Index of "ESEL=" in the list.
        #######################################################################
        """
        index = [i for i, str in enumerate(esel_list) if 'ESEL=' in str]
        return index[0]
<commit_msg>Add BMC build timestamp in FFDC<commit_after>#!/usr/bin/python
r"""
#############################################################
#    @file     openbmc_ffdc_list.py
#
#    @brief    List for FFDC ( First failure data capture )
#              commands and files to be collected as a part
#              of the test case failure.
#############################################################
"""

# -------------------
# FFDC default list
# -------------------

# -----------------------------------------------------------------
# Dict Name {  Index string : { Key String :  Comand string} }
# -----------------------------------------------------------------
# Add cmd's needed to be part of the ffdc report manifest file
FFDC_BMC_CMD = {
    'DRIVER INFO':
    {
        # String Name         Command
        'FW Level': 'cat /etc/os-release',
        'FW Timestamp': 'cat /etc/timestamp',
    },
    'BMC DATA':
    {
        'BMC OS': 'uname -a',
        'BMC Uptime': 'uptime',
        'BMC File System Disk Space Usage': 'df -hT',
    },
    'APPLICATION DATA':
    {
        'BMC state': '/usr/sbin/obmcutil state',
    },
}

# Add file name and correcponding command needed for BMC
FFDC_BMC_FILE = {
    'BMC FILES':
    {
        # File Name         Command
        'BMC_proc_list': 'top -n 1 -b',
        'BMC_proc_fd_active_list': 'ls -Al /proc/*/fd/',
        'BMC_journalctl': 'journalctl --no-pager',
        'BMC_dmesg': 'dmesg',
        'BMC_procinfo': 'cat /proc/cpuinfo',
        'BMC_meminfo': 'cat /proc/meminfo',
    },
}

# Add file name and correcponding command needed for all Linux distributions
FFDC_OS_ALL_DISTROS_FILE = {
    'OS FILES':
    {
        # File Name         Command
        'OS_msglog': 'cat /sys/firmware/opal/msglog',
        'OS_cpufrequency': 'ppc64_cpu --frequency',
        'OS_dmesg': 'dmesg',
        'OS_boot': 'cat /var/log/boot.log',
        'OS_procinfo': 'cat /proc/cpuinfo',
        'OS_meminfo': 'cat /proc/meminfo',
        'OS_netstat': 'netstat -a',
        'OS_lspci': 'lspci',
        'OS_lscpu': 'lscpu',
        'OS_lscfg': 'lscfg',
    },
}

# Add file name and correcponding command needed for Ubuntu Linux
FFDC_OS_UBUNTU_FILE = {
    'OS FILES':
    {
        # File Name         Command
        'OS_isusb': 'lsusb -t ; lsusb -v',
        'OS_kern': 'tail -n 50000 /var/log/kern.log',
        'OS_authlog': 'cat /var/log/auth.log; cat /var/log/auth.log.1',
        'OS_syslog': 'tail -n 200000 /var/log/syslog',
        'OS_info': 'uname -a; dpkg -s opal-prd; dpkg -s ipmitool',
    },
}

# Add file name and correcponding command needed for RHEL Linux
FFDC_OS_RHEL_FILE = {
    'OS FILES':
    {
        # File Name         Command
        'OS_rsct': '/usr/bin/ctversion -bv',
        'OS_secure': 'cat /var/log/secure',
        'OS_syslog': 'tail -n 200000 /var/log/messages',
        'OS_info': 'lsb_release -a; cat /etc/redhat-release; uname -a; rpm -qa',
    },
}

# Add file name and correcponding command needed for RHEL Linux
FFDC_OS_IBM_POWERKVM_FILE = {
    'OS FILES':
    {
        # File Name         Command
        'OS_secure': 'cat /var/log/secure',
        'OS_syslog': 'tail -n 200000 /var/log/messages',
        'OS_info': 'lsb_release -a; uname -a; rpm -qa',
    },
}

# Enable when ready with openbmc/openbmc-test-automation#203
# replace with new path /xyz/openbmc_project
OPENBMC_BASE = '/org/openbmc/'
ENUMERATE_SENSORS = OPENBMC_BASE + 'sensors/enumerate'
# TODO: Use the xyz enums once moved to xyz completely
# ENUMERATE_SYSTEMS = OPENBMC_BASE + 'inventory/enumerate'
ENUMERATE_SYSTEMS = '/xyz/openbmc_project/inventory/enumerate'
ENUMERATE_ELOG = '/xyz/openbmc_project/logging/entry/enumerate'
ENUMERATE_EVENTS = OPENBMC_BASE + 'records/events/enumerate'
ENUMERATE_LED = OPENBMC_BASE + 'control/led/enumerate'

# Sensors/control data.
ENUMERATE_SENSOR = '/xyz/openbmc_project/sensors/enumerate'
ENUMERATE_CONTROL = '/xyz/openbmc_project/control/enumerate'

# Add file name and correcponding Get Request
FFDC_GET_REQUEST = {
    'GET REQUESTS':
    {
        # File Name         Command
        'BMC_sensor_list': ENUMERATE_SENSORS,
        'BMC_sensor_xyz_list': ENUMERATE_SENSOR,
        'BMC_control_list': ENUMERATE_CONTROL,
        'BMC_inventory': ENUMERATE_SYSTEMS,
        'BMC_elog': ENUMERATE_ELOG,
        'BMC_led': ENUMERATE_EVENTS,
        'BMC_record_log': ENUMERATE_LED,
    },
}

# Define your keywords in method/utils and call here
FFDC_METHOD_CALL = {
    'BMC LOGS':
    {
        # Description             Keyword name
        'FFDC Generic Report': 'BMC FFDC Manifest',
        'BMC Specific Files': 'BMC FFDC Files',
        'Get Request FFDC': 'BMC FFDC Get Requests',
        'OS FFDC': 'OS FFDC Files',
        'Core Files': 'SCP Coredump Files',
        'SEL Log': 'Collect eSEL Log',
    },
}

# -----------------------------------------------------------------

# base class for FFDC default list
class openbmc_ffdc_list():

    def get_ffdc_bmc_cmd(self, i_type):
        r"""
        ########################################################################
        #   @brief    This method returns the list from the dictionary for cmds
        #   @param    i_type: @type string: string index lookup
        #   @return   List of key pair from the dictionary
        ########################################################################
        """
        return FFDC_BMC_CMD[i_type].items()

    def get_ffdc_bmc_file(self, i_type):
        r"""
        ########################################################################
        #   @brief    This method returns the list from the dictionary for scp
        #   @param    i_type: @type string: string index lookup
        #   @return   List of key pair from the dictionary
        ########################################################################
        """
        return FFDC_BMC_FILE[i_type].items()

    def get_ffdc_get_request(self, i_type):
        r"""
        ########################################################################
        #   @brief    This method returns the list from the dictionary for scp
        #   @param    i_type: @type string: string index lookup
        #   @return   List of key pair from the dictionary
        ########################################################################
        """
        return FFDC_GET_REQUEST[i_type].items()

    def get_ffdc_cmd_index(self):
        r"""
        ########################################################################
        #   @brief    This method returns the list index from dictionary
        #   @return   List of index to the dictionary
        ########################################################################
        """
        return FFDC_BMC_CMD.keys()

    def get_ffdc_get_request_index(self):
        r"""
        ########################################################################
        #   @brief    This method returns the list index from dictionary
        #   @return   List of index to the dictionary
        ########################################################################
        """
        return FFDC_GET_REQUEST.keys()

    def get_ffdc_file_index(self):
        r"""
        ########################################################################
        #   @brief    This method returns the list index from dictionary
        #   @return   List of index to the dictionary
        ########################################################################
        """
        return FFDC_BMC_FILE.keys()

    def get_ffdc_method_index(self):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   Index of the method dictionary
        ########################################################################
        """
        return FFDC_METHOD_CALL.keys()

    def get_ffdc_method_desc(self,
                             index):
        r"""
        ########################################################################
        #   @brief   This method returns the just the keys from the dictionary.
        #   @return  List of ffdc descriptions.
        ########################################################################
        """
        return FFDC_METHOD_CALL[index].keys()

    def get_ffdc_method_call(self, i_type):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   List of key pair keywords
        ########################################################################
        """
        return FFDC_METHOD_CALL[i_type].items()

    def get_ffdc_os_all_distros_index(self):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   Index of the method dictionary
        ########################################################################
        """
        return FFDC_OS_ALL_DISTROS_FILE.keys()

    def get_ffdc_os_all_distros_call(self, i_type):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   List of key pair keywords
        ########################################################################
        """
        return FFDC_OS_ALL_DISTROS_FILE[i_type].items()

    def get_ffdc_os_distro_index(self, distro):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   Index of the method dictionary
        ########################################################################
        """
        distro_file = "FFDC_OS_" + str(distro).upper() + "_FILE"
        return eval(distro_file).keys()

    def get_ffdc_os_distro_call(self, i_type, distro):
        r"""
        ########################################################################
        #   @brief    This method returns the key pair from the dictionary
        #   @return   List of key pair keywords
        ########################################################################
        """
        distro_file = "FFDC_OS_" + str(distro).upper() + "_FILE"
        return eval(distro_file)[i_type].items()

    def get_strip_string(self, i_str):
        r"""
        ########################################################################
        #   @brief    Returns the stripped strings
        #   @param    i_str: @type string: string name
        #   @return   Remove all special chars and return the string
        ########################################################################
        """
        return ''.join(e for e in i_str if e.isalnum())

    def get_esel_index(self, esel_list):
        r"""
        #######################################################################
        #   @brief    Returns the eSEL binary index.
        #   @param    esel_ist: @type list: eSEL list.
        #   @return   Index of "ESEL=" in the list.
        #######################################################################
        """
        index = [i for i, str in enumerate(esel_list) if 'ESEL=' in str]
        return index[0]
<|endoftext|>