Since all Ansible modules ever written are using worst practice Python,
the module loader must be rewritten to cope with their horrors.
Ansible is woeful software:
* AnsibleModule argument declarations appear within the main() function,
so they can't be introspected prior to execution.
* No if __name__ == '__main__' guard means they can't be introspected
without triggering execution.
* By default the main() function attempts to read from stdin, hanging
our IO thread.
* So much unspeakable crap.
This rewrites the module loader to avoid actually running a module if it
can possibly be avoided. The downside is that the new loader must be
aware of far more details of the Python module mechanism. For example
with the new importer, namespace packages are broken at the very least.
On the plus side, now the module loader will be able to cope with
Django.
* Start splitting docs up into internals.rst / api.rst
* Docs for lots more of econtext.core.
* Get rid of _update_stream() and has_output(), replace with individual
functions called as state changes.
* Add Broker.on_thread() and remove Stream._lock: simply call
on_thread() to ensure buffer management is linearized.
* Rename read_side/write_side to receive_side/transmit_side like event
handler names.
* Clean up some more repr / debug logs.
* Move handle cleanup to Context.on_shutdown where it belongs.
* Make wake() a noop when called from broker thread.
* Replace graceful_count crap with Side.graceful attribute, add
Broker.keep_alive() to check whether any registered readers want to
be kept alive for graceful shutdown() or any child contexts with a
connected stream exist.
* Make master.Broker timeout slightly longer than slave broker.
* Add generic on_thread() to allow running code on the IO thread.
* Use TLS to track whether importer is currently running. Avoids
needing to maintain an ignore stack.
* Print more debugging around cases where Importer skips a module.
* If a module is part of a package, import the package and examine its
__loader__. If we are not the loader, refuse to load it.