grim/pyscovery

Update the homepage for the new home
draft default tip
2020-04-27, Gary Kramlich
367b9e9dadad
Update the homepage for the new home
# pyscovery - A python plugin finder
# Copyright (C) 2013-2014 Gary Kramlich <grim@reaperworld.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
pyscovery is a Python plugin loader that will search for classes based from a
list of modules and optionally use the file system to recurse into packages.
This is different from pkg_resources and friends since it doesn't require you
to add every module that might have packages, it will discover it for you.
I wrote this because none of the existing solutions fit my need of being able
to logically group similar plugins in the filesystem.
"""
import importlib
import inspect
import pkgutil
__version__ = '1.3'
class Loader(object):
""" A pyscovery loader """
def __init__(self):
pass
def find(self, cls, path, create, *args, **kwargs):
"""Find all plugins that are subclasses of cls.
:param cls: The class whose subclasses to find.
:type cls: class
:param path: The path to look for packages in.
:type path: string
:param create: return instances rather than just return their class.
:type create: bool
:param args: Additional arguments to pass to each constructor. Ignored if
create is False.
:type args: arguments
:param kwargs: Additional keyword arguements to pass to each constructor.
Ignored if create is False.
:type kwargs: kwargs
:returns: Generator of subclasses of cls
"""
if not inspect.isclass(cls):
raise TypeError('{} is not a class instance'.format(cls))
cls_name = cls.__name__
for _, name, _ in pkgutil.walk_packages(path):
mod = importlib.import_module(name)
for symbol_name in dir(mod):
if symbol_name == cls_name:
continue
symbol = getattr(mod, symbol_name, None)
if not inspect.isclass(symbol):
continue
if inspect.isabstract(symbol):
continue
if not issubclass(symbol, cls):
continue
if create:
yield symbol(*args, **kwargs)
else:
yield symbol
_DEFAULT_LOADER = Loader()
def find(cls, recurse, create, *args, **kwargs):
"""Find all plugins that are subclasses of cls in the current search paths
:param cls: The class whose subclasses to find.
:type cls: class
:param recurse: Whether or not to recurse into packages.
:type recurse: bool
:param create: return instances rather than just return their class.
:type create: bool
:param args: Additional arguments to pass to each constructor. Ignored if
create is False.
:type args: arguments
:param kwargs: Additional keyword arguements to pass to each constructor.
Ignored if create is False.
:type kwargs: kwargs
:returns: Generator of subclasses of cls
"""
return _DEFAULT_LOADER.find(cls, recurse, create, *args, **kwargs)