grim/pyscovery
Clone
Summary
Browse
Changes
Graph
cleaned up the readme for the rename and threw it in pyscovery.py as the docstring
2013-03-29, Gary Kramlich
188ade45b513
cleaned up the readme for the rename and threw it in pyscovery.py as the docstring
# pyplugin - A python plugin finder
# Copyright (C) 2013 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/>.
import
fnmatch
import
importlib
import
inspect
import
os
# we use a list since it is a mutable sequence type. Meaning we can add to it
# while iterating.
MODULES
=
[]
__version__
=
'1.0'
def
add_module
(
module
):
"""
Adds a module to search for plugins under
"""
global
MODULES
# pylint:disable-msg=W0602
if
not
module
in
MODULES
:
MODULES
.
append
(
module
)
def
remove_module
(
module
):
"""
Removes a module to search for plugins under
"""
global
MODULES
# pylint:disable-msg=W0602
if
module
in
MODULES
:
MODULES
.
remove
(
module
)
def
get_modules
():
"""
Returns the list of all module to search under
"""
return
MODULES
def
clear_modules
():
"""
Clears all search modules
"""
MODULES
[:]
=
[]
def
find
(
cls
,
recurse
=
False
):
"""
Find all plugins that are subclasses of cls in the current search paths
"""
if
not
inspect
.
isclass
(
cls
):
raise
TypeError
(
'
{}
is not a class instance'
)
cls_name
=
cls
.
__name__
for
module
in
MODULES
:
mod
=
importlib
.
import_module
(
module
)
if
recurse
and
_is_package
(
mod
):
_recurse
(
mod
)
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
yield
symbol
def
_is_package
(
module
):
"""
Returns true if the module's name is __init__, false otherwise
"""
filename
=
os
.
path
.
basename
(
module
.
__file__
)
base
,
_
=
os
.
path
.
splitext
(
filename
)
return
base
==
'__init__'
def
_recurse
(
module
):
"""
Adds additional modules from a package
"""
dirname
=
os
.
path
.
dirname
(
module
.
__file__
)
make_module
=
lambda
name
:
'.'
.
join
((
module
.
__name__
,
name
))
for
name
in
os
.
listdir
(
dirname
):
base
,
_
=
os
.
path
.
splitext
(
name
)
if
base
==
'__init__'
:
continue
filename
=
os
.
path
.
join
(
dirname
,
name
)
if
os
.
path
.
isdir
(
filename
):
add_module
(
make_module
(
base
))
elif
os
.
path
.
isfile
(
filename
):
if
fnmatch
.
fnmatch
(
name
,
'*.py'
)
or
\
fnmatch
.
fnmatch
(
name
,
'*.py[co]'
):
add_module
(
make_module
(
base
))
else
:
print
name
__all__
=
[
add_module
,
remove_module
,
get_modules
,
clear_modules
,
find
]