@@ -0,0 +1,3116 @@
+import sys%0Aimport os%0Aimport inspect%0Aimport itertools%0Aimport pkgutil%0Aimport importlib%0A%0Aimport biokit.converters%0A%0A%0Aclass Registry(object):%0A%0A    def __init__(self):%0A        self._registry = %7B%7D%0A        self._fill_registry(biokit.converters.__path__)%0A%0A%0A    def _fill_registry(self, path):%0A        %22%22%22%0A        Explore the directory converters to discover all converter classes%0A        (a concrete class which inherits from :class:%60ConvBase%60)%0A        and fill the register with the all input extensions, output extensions associated to this converter%0A%0A        :param str path: the path of a directory to explore (not recursive)%0A        %22%22%22%0A%0A        def is_converter(item):%0A            obj_name, obj = item%0A            if not inspect.isclass(obj):%0A                return False%0A            return issubclass(obj, biokit.converters.base.ConvBase) and not inspect.isabstract(obj)%0A%0A        modules = pkgutil.iter_modules(path=path)%0A        for _ ,module_name , *_ in modules :%0A            if module_name not in ('__init__', 'base', 'registry'):%0A                try:%0A                    module = importlib.import_module(%22biokit.converters.%22 + module_name)%0A                except (ImportError, TypeError) as err:%0A                    print(%22%3E%3E%3E WARNING skip module '%7B%7D': %7B%7D %3C%3C%3C%22.format(module_name, err, file=sys.stderr))%0A                    continue%0A                converters = inspect.getmembers(module)%0A                converters = %5Bc for c in converters if is_converter(c)%5D%0A                for converter_name, converter in converters:%0A                    if converter is not None:%0A                        all_conv_path = itertools.product(converter.input_ext, converter.output_ext)%0A                        for conv_path in all_conv_path:%0A                            self%5Bconv_path%5D = converter%0A%0A%0A    def __setitem__(self, conv_path, value):%0A        %22%22%22%0A        Set new%0A        :param conv_path: the input extension, the output extension%0A        :type conv_path: tuple of 2 strings%0A        :param value: the convertor which handle the conversion from input_ext -%3E output_ext%0A        :type value: :class:%60ConvBase%60 object%0A        %22%22%22%0A        if conv_path in self._registry:%0A            raise KeyError('an other converter already exist for %7B%7D -%3E %7B%7D'.format(*conv_path))%0A        self._registry%5Bconv_path%5D = value%0A%0A%0A    def __getitem__(self, conv_path):%0A        %22%22%22%0A%0A        :param conv_path: the input extension, the output extension%0A        :type conv_path: tuple of 2 strings%0A        :return: an object of subclass o :class:%60ConvBase%60%0A        %22%22%22%0A        return self._registry%5Bconv_path%5D%0A%0A%0A    def __contains__(self, conv_path):%0A        %22%22%22%0A        can use membership operation on registry%0A%0A        :param conv_path: the input extension, the output extension%0A        :type conv_path: tuple of 2 strings%0A        :return: True if conv_path is in registry otherwise False.%0A        %22%22%22%0A        return conv_path in self._registry%0A%0A%0A    def __iter__(self):%0A        %22%22%22%0A        make registry iterable through conv_path (str input extension, str output extension)%0A        %22%22%22%0A        for path in self._registry:%0A            yield path%0A%0A

add registry to dicover and register converters