importscan¶
-
importscan.
scan
(package, ignore=None, handle_error=None)¶ Scan a package by importing it.
A framework can provide registration decorators: a decorator that when used on a class or a function causes it to be registered with the framework. Metaclasses can also be used for this effect. As a consequence of this, registration only takes place when the module is actually imported. You can do this import explicitly in your code. It can however also be convenient to import everything in a package all at once automatically. This is what
scan
does.This function was extracted and refactored from the
Venusian
library which also provides infrastructure for finding such decorators.Parameters: - package – A reference to a Python package or module object.
- ignore –
Ignore certain modules or packages during a scan. It should be a sequence containing strings and/or callables that are used to match against the dotted name of a module encountered during a scan. The sequence can contain any of these three types of objects:
- A string representing a dotted name. For example, if you want
to ignore the
my.package
package and any of its submodules during the scan, passignore=['my.package']
. - A string representing a relative dotted name, a string
starting with a dot. The relative module or package is
relative to the
package
being scanned, so this does not match deeper relative packages.For example, if the
package
you’ve passed is imported asmy.package
, and you passignore=['.mymodule']
, themy.package.mymodule
mymodule and any of its submodules are omitted during scan processing. Butmy.package.sub.mymodule
is not ignored asmymodule
is nested insub
. - A callable that accepts a dotted name indicating a module or a
package as its single positional argument and returns
True
orFalse
. For example, if you want to skip all packages and modules with a full dotted path that ends with the word “tests”, you can useignore=[re.compile('tests$').search]
. If the callable returnsTrue
(or anything else truthy), the object is ignored, if it returnsFalse
(or anything else falsy) the object is not ignored.
You can mix and match the three types of strings in the list. For example, if the package being scanned is
my
,ignore=['my.package', '.someothermodule', re.compile('tests$').search]
would causemy.package
(and all its submodules and subobjects) to be ignored,my.someothermodule
to be ignored, and any modules, packages, or global objects found during the scan that have a full dotted name that ends with the wordtests
to be ignored.Packages and modules matched by any ignore in the list are not imported, and their top-level (registration) code is not run as a result.
You can also pass in a string or callable by itself as a single non-list argument.
- A string representing a dotted name. For example, if you want
to ignore the
- handle_error –
A callback function that is called when an exception is raised during the importing process. By default
scan
propagates all errors that happen during the import process, includingImportError
. If you use a customhandle_error
callback, you can change this behavior by not reraising the error.Here’s an example
handle_error
callback that ignoresImportError
but not any other errors:def handle_error(name, e): if not isinstance(e, ImportError): raise e
The first argument passed to
handle_error
is the module or package dotted name that could not be imported due to an exception. The second argument is the exception object. Ifhandle_error
does not re-raise the error, the error is suppressed.