def test_module_name_from_path_1(self):

        package_name = 'pylabcontrol'

        filename = inspect.getmodule(ExampleScript).__file__
        # check that file actually exists
        assert os.path.isfile(filename)

        module, path = module_name_from_path(filename, verbose=False)

        assert module == 'pylabcontrol.scripts.script_dummy'
        assert path == os.path.normpath(filename.split(package_name)[0])
Esempio n. 2
0
def find_exportable_in_python_files(folder_name, class_type, verbose=True):
    """
    load all the instruments or script objects that are located in folder_name and
    return a dictionary with the script class name and path_to_python_file
    Args:
        folder_name (string): folder in which to search for class objects / or name of module
        class_type (string or class): class type for which to look for

    Returns:
        a dictionary with the class name and path_to_python_file:
        {
        'class': class_of_instruments,
        'filepath': path_to_python_file
        }
    """

    # if the module name was passed instead of a filename, figure out the path to the module
    if not os.path.isdir(folder_name):
        try:
            folder_name = os.path.dirname(
                inspect.getfile(import_module(folder_name)))
        except ImportError:
            raise ImportError('could not find module ' + folder_name)

    subdirs = [
        os.path.join(folder_name, x) for x in os.listdir(folder_name) if
        os.path.isdir(os.path.join(folder_name, x)) and not x.startswith('.')
    ]

    classes_dict = {}
    # if there are subdirs in the folder recursively check all the subfolders for scripts
    for subdir in subdirs:
        classes_dict.update(find_exportable_in_python_files(
            subdir, class_type))

    if class_type.lower() == 'instrument':
        class_type = Instrument
    elif class_type.lower() == 'script':
        class_type = Script

    for python_file in [
            f for f in glob.glob(os.path.join(folder_name, "*.py"))
            if '__init__' not in f and 'setup' not in f
    ]:
        module, path = module_name_from_path(python_file)

        #appends path to this module to the python path if it is not present so it can be used
        if path not in sys.path:
            sys.path.append(path)

        try:
            module = import_module(module)

            classes_dict.update({
                name: {
                    'class': name,
                    'filepath': inspect.getfile(obj),
                    'info': inspect.getdoc(obj)
                }
                for name, obj in inspect.getmembers(module)
                if inspect.isclass(obj) and issubclass(obj, class_type)
                and not obj in (Instrument, Script, ScriptIterator)
            })

        except (ImportError, ModuleNotFoundError) as e:
            print(e)
            if verbose:
                print('Could not import module', module)

    return classes_dict
Esempio n. 3
0
    def load_and_append(instrument_dict, instruments=None, raise_errors=False):
        """
        load instrument from instrument_dict and append to instruments

        Args:
            instrument_dict: dictionary of form

                instrument_dict = {
                name_of_instrument_1 :
                    {"settings" : settings_dictionary, "class" : name_of_class}
                name_of_instrument_2 :
                    {"settings" : settings_dictionary, "class" : name_of_class}
                ...
                }

            or

                instrument_dict = {
                name_of_instrument_1 : name_of_class,
                name_of_instrument_2 : name_of_class
                ...
                }

            where name_of_class is either a class or a dictionary of the form {class: name_of__class, filepath: path_to_instr_file}

            instruments: dictionary of form

                instruments = {
                name_of_instrument_1 : instance_of_instrument_1,
                name_of_instrument_2 : instance_of_instrument_2,
                ...
                }

            raise_errors: if true errors are raised, if False they are caught but not raised



        Returns:
                dictionary updated_instruments that contains the old and the new instruments

                and list loaded_failed = [name_of_instrument_1, name_of_instrument_2, ....] that contains the instruments that were requested but could not be loaded

        """
        if instruments is None:
            instruments = {}

        updated_instruments = {}
        updated_instruments.update(instruments)
        loaded_failed = {}

        for instrument_name, instrument_class_name in instrument_dict.items():
            instrument_settings = None
            module = None

            # check if instrument already exists
            if instrument_name in list(instruments.keys()) \
                    and instrument_class_name == instruments[instrument_name].__name__:
                print(
                    ('WARNING: instrument {:s} already exists. Did not load!'.
                     format(instrument_name)))
                loaded_failed[instrument_name] = instrument_name
            else:
                instrument_instance = None

                if instrument_class_name is None:
                    loaded_failed[
                        instrument_name] = "Instrument class name returned None."
                elif isinstance(instrument_class_name, dict):
                    if 'settings' in instrument_class_name:
                        instrument_settings = instrument_class_name['settings']
                    instrument_filepath = str(
                        instrument_class_name['filepath'])
                    instrument_class_name = str(instrument_class_name['class'])
                    path_to_module, _ = module_name_from_path(
                        instrument_filepath, verbose=False)
                    module = import_module(path_to_module)
                    class_of_instrument = getattr(module,
                                                  instrument_class_name)
                    try:
                        if instrument_settings is None:
                            # this creates an instance of the class with default settings
                            instrument_instance = class_of_instrument(
                                name=instrument_name)
                        else:
                            # this creates an instance of the class with custom settings
                            instrument_instance = class_of_instrument(
                                name=instrument_name,
                                settings=instrument_settings)
                    except Exception as e:
                        loaded_failed[instrument_name] = e
                        print('loading ' + instrument_name + ' failed:')
                        print(traceback.format_exc())
                        if raise_errors:
                            raise e
                        continue
                elif isinstance(instrument_class_name, Instrument):
                    instrument_class_name = instrument_class_name.__class__
                    instrument_filepath = os.path.dirname(
                        inspect.getfile(instrument_class_name))

                    # here we should also create an instrument instance at some point as in the other cases...
                    # instrument_instance =
                    raise NotImplementedError
                elif issubclass(instrument_class_name, Instrument):
                    class_of_instrument = instrument_class_name
                    try:
                        if instrument_settings is None:
                            # this creates an instance of the class with default settings
                            instrument_instance = class_of_instrument(
                                name=instrument_name)
                        else:
                            # this creates an instance of the class with custom settings
                            instrument_instance = class_of_instrument(
                                name=instrument_name,
                                settings=instrument_settings)
                    except Exception as e:
                        loaded_failed[instrument_name] = e
                        # print(instrument_name, ': ', str(e))
                        print('loading ' + instrument_name + ' failed:')
                        print(traceback.format_exc())
                        if raise_errors:
                            raise e
                        continue

                updated_instruments[instrument_name] = instrument_instance

        return updated_instruments, loaded_failed
Esempio n. 4
0
def get_classes_in_folder(folder_name, class_type, verbose=False):
    """
    load all the instruments or script objects that are located in folder_name and
    return a dictionary with the script class name and path_to_python_file
    Args:
        folder_name (string): folder in which to search for class objects / or name of module
        class_type (string or class): class type for which to look for

    Returns:
        a dictionary with the class name and path_to_python_file:
        {
        'class': class_of_instruments,
        'filepath': path_to_python_file
        }

    """

    assert class_type == Instrument or class_type == Script or class_type.lower(
    ) in ['instrument', 'script']

    if isinstance(class_type, str):
        if class_type.lower() == 'instrument':
            class_type = Instrument
        elif class_type.lower() == 'script':
            class_type = Script

    # if the module name was passed instead of a filename, figure out the path to the module
    if not os.path.isdir(folder_name):
        try:
            folder_name = os.path.dirname(
                inspect.getfile(import_module(folder_name)))
        except ImportError:
            raise ImportError('could not find module ' + folder_name)

    subdirs = [
        os.path.join(folder_name, x) for x in os.listdir(folder_name) if
        os.path.isdir(os.path.join(folder_name, x)) and not x.startswith('.')
    ]

    classes_dict = {}
    # if there are subdirs in the folder recursively check all the subfolders for scripts
    for subdir in subdirs:
        classes_dict.update(get_classes_in_folder(subdir, class_type))

    for python_file in [
            f for f in glob.glob(os.path.join(folder_name, "*.py"))
            if '__init__' not in f
    ]:
        module, path = module_name_from_path(python_file)

        try:
            module = import_module(module)

            classes_dict.update({
                name: {
                    'class': name,
                    'filepath': inspect.getfile(obj)
                }
                for name, obj in inspect.getmembers(module)
                if inspect.isclass(obj) and issubclass(obj, class_type)
                and not obj in (Instrument, Script, ScriptIterator)
            })
        except ImportError as e:
            if verbose:
                print(('Could not import module', module))
                print(e)

    return classes_dict