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])
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
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
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