ELI5-ification underway\!

This commit is contained in:
Elf M. Sternberg 2016-09-02 21:12:04 -07:00
parent 6506acd861
commit 67e57d7492
29 changed files with 873 additions and 118 deletions

View File

@ -1,67 +1,65 @@
Synopsis
--------
**Polyloader** is a python module that enables the discovery and loading
of heterogenous source code packages. This discovery and loading is
critical to the functioning of other programming languages that use the
Python AST and Python interpreter, languages such as Hy, Doge, and
Mochi.
Problem Statement
-----------------
The Python module loader system is hard-coded to prevent the discovery
of heterogenous source code packages. From Python 2.6 through the
current (as of this writing) Python 3.5, the import mechanism allows for
the creation of file finders and importers that would transform Python's
import syntax into a *path,* assert whether or not that path could be
made to correspond to a *syntax object*, and then attempt to *load* that
syntax object as a Python module. Python *packages*, however, are
assumed to be uniformly made up of Python syntax objects, be they
**.py** source files, **.pyc/.pyo** bytecode, or **.so/.dll** files with
an exposed Python-to-C API. In Python 2 these suffixes are hard-coded
into the source in the **imp** builtin module; in Python 3 these
suffixes are constants defined in a private section of **importlib**; in
either case, they are unavailable for modification. This lack of access
to the extensions list prevents the *discovery* of heterogenous source
**Polyloader** is a python module that extends the Python `import`
statement to enable the discovery and loading of heterogenous source
code packages.
The discovery mechanism is outlined in Python's **pkgutil** module;
features such as **pkgutil.iter_modules** do not work with heterogenous
source code, which in turn means that one cannot write, for one
important example, Django management commands in an alternative syntax.
Say What?
---------
**polyloader** is a Python module that intercepts calls to the default
finder, loader, and package module iterator, and if the path resolves to
an alternative syntax, provide the appropriate finder, loader and
iterator. **polyloader** is different from traditional importlib shims
in that it directly affects the default source file loader, and thus
allows for the discovery and importation of suffixes not listed in
Python's defaults.
The ``import`` statement is how the Python interpreter finds a module
written in Python and loads it, turning it into variables, executable
functions, constructable classes, and other Python objects, and then
exposes those objects to the currently running program.
To use:
-------
The ``import`` statement has long been extensible so that things other
than Python code could be imported, but this feature has always had two
limitations:
Import polyloader in your python script's launcher or library, as well
as the syntax compiler(s) you plan to use. For example, if you have
`Mochi <https://github.com/i2y/mochi>`__ and
`Hy <http://docs.hylang.org/en/latest/>`__ installed, and you wanted to
write a Django app, edit manage.py and add the following lines at the
top:
1. It's annoyingly hard to write an importer. (Believe me. Polyloader
*is* one!)
2. For filesystem-based modules (which is 99% of them) Python's importer
only understands one loader type per directory. It's not possible to
store code or data written in something other than Python in the same
directory with Python module code and load it via ``import``.
::
The former requires a certain degree of abstraction and thought. For
the latter, most people ignore the problem and load module configuration
files written in JSON or YAML or whatever directly. This is fine,
except when you want to write in one of Python's extended languages like
Hy or Coconut in a framework like Django, Flask or Glitch.
from mochi.main import compile_file as mochi_compile
from hy.importer import ast_compile as hy_compile
from polyloader import polyimport
polyimport(mochi_compile, ['.mochi'])
polyimport(hy_compile, ['.hy'])}
**Polyloader** eliminates these limitations.
Now your views can be written in Hy and your models in Mochi, and
everything will just work.
What's the real problem?
------------------------
Dependencies
------------
The real problem is that Python's traditional extensions, ``.py``,
``.pyc/.pyo``, and ``.so/.dll`` files, are hard-coded in Python. In
Python 2, they're in the ``imp`` builtin; In Python 3, they're defined
in a private section of `importlib`. Either way, they're not accessible
for modification and extension.
This problem is made harder by the ``pkglib`` module, which is part of
Python's standard library. This module uses ``inspect.getmoduleinfo``,
which again only recognizes the usual extensions. Which means you can't
list multilingual modules either; this hampers the development of Django
management commands in a syntax other than Python.
What the solution?
------------------
At its heart, the Python import system runs two different internal
mechanisms to figure out what the *import string* (the dotted terms
after the word "import") "means." Each mechanism has one or more
*finders*, and the first finder to report "I have a *loader* that knows
what that import string means" wins.
The very last finder is for the filesystem. The solution is to get in
front of that finder with one that can handle all the other syntax
loaders *and* knows how to fall back on the last one for those files the
last one handles.
That's what ``polyloader`` does.
polymorph is self-contained. It has no dependencies other than Python
itself and your choice of language.

111
docs/_sources/details.txt Normal file
View File

@ -0,0 +1,111 @@
Details on Import and Polyloader
================================
Welcome to the Python Import ELI5!
**********************************
What is `import`?
-----------------
``import`` is a Python statement that finds a *module* that is accessible
by the currently running process, loads it, and makes its contents
available to the scope in which the statement was made. A statement
like
``import django.db.models``
is looking for a module named ``django.db.models``. If the statement is
successful, ``django.db.models`` will be a variable name in the scope,
it will be a Python *object* (of ``class Module``, but that's not
important), and it will have functions, class constructors, variables
and constants. These Python objects will be accessible through the dot
operator.
An alternative way of writing import statements is
``from django.utils import encoding``
And then the variable will just be ``encoding``. The ``encoding``
module has a function for handling unicode-to-web translation.
Accessing it through the dot operator, it looks like this:
``ready_str = encoding.smart_str(unready_str)``
We call the parts of the import statement that describe the module the
*import string*.
``sys.path_hooks``: How does Python know where to look?
-------------------------------------------------------
That's what's funny. Python has two independent ways of making sense of
of the import string. The old system is based on the assumption that
everything is a filesystem, with folders and filenames. This is called
the ``sys.path_hooks`` system.
In the old system, the parts of the import string would be split up, and
then a collection of directories would be scanned to see if the first
name in the import string could be matched with a subdirectory. If it
could, that directory would be scanned until the last name on the import
string. If that name was a *filename*, it would be loaded as a module.
If that name was a *directory* and that directory had a file named
``__init__.py``, then that file would be loaded as the module.
The ``sys.path_hooks`` array has a list of different methods for trying to
scan a filesystem for the parts of the import string. A ``path_hook`` is
a function that takes a path to a directory; if it can handle the
contents of the directory, it returns a **Finder**, an object whose job
is to figure out how to load the module; if it can't, it returns an
ImportError exception. The object that loads the module is called,
naturally, a **Loader**.
* To read more about **Finders**, see :ref:`eli5-finders`
* To read more about **Loaders**, see :ref:`eli5-loaders`
* To read more about **Path Hooks**, see :ref:`eli5-pathhooks`
``sys.path``: What directories are searched?
--------------------------------------------
The list of directories is stored in an array, ``sys.path``. This path is
initialized by Python when it starts up, but programs can modify it at
run-time to point to extra directories if they want.
``sys.meta_path``: What is the new system?
------------------------------------------
The new system is called ``sys.meta_path``, and it's an array of
**Finders**, objects that have one method, ``find_module(fullname)``.
It's an anything-goes API that gives developers the freedom to import
modules from anywhere: databases, archives, remote web resources, even
code written on-the-fly internally. The new system can apply any
meaning at all to the import string.
In Python, the import string is offered to each object in
``sys.meta_path`` before being offered to each ``sys.path_hook``. The
filesystem is typically the last finder tried.
To read more about **Meta Paths**, see :ref:`eli5-metapaths`
Is it different between Python 2 and Python 3?
---------------------------------------------
Python 3 moves almost everything about this process into python's
library, leaving only a bare minimum of functionality inside the Python
executable to load this library and run it. When the Python developers
did that, they added a lot of functionality to make it easier to write
new import modules. The old way still works, but there are now *Module
Specifications*, which are metadata about a module, and the old
``path_hooks`` system is now just a ``meta_path`` handler added to the
new system as the last resort.
To read more about **Module Specifications**, see :ref:`eli5-specs`
Does the old system still matter?
---------------------------------
Yes, for one reason: *iteration*. Iteration is the ability to take a
path where you believe Python modules can be found, and list through
them. This facility is useful for large frameworks where a user wants
to add new commands, or new objects, or new operations; Django uses this
facility a lot! The ``pkgutil`` library depends upon Finders being able
to iterate their contents.

37
docs/_sources/eli5.txt Normal file
View File

@ -0,0 +1,37 @@
ELI5: Explain Like I'm Five!
============================
.. _eli5-finders:
Finders
=======
TODO
.. _eli5-loaders:
Loaders
=======
TODO
.. _eli5-pathhooks:
Path Hooks
==========
TODO
.. _eli5-metapaths:
Meta Paths
==========
TODO
.. _eli5-specs:
Module Specifications
=====================
TODO

View File

@ -3,8 +3,8 @@
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to py-polymorphic-loader's documentation!
======================================
Welcome to polyloader
=====================
Contents:
@ -14,6 +14,7 @@ Contents:
readme
installation
usage
details
contributing
authors
history

View File

@ -8,11 +8,11 @@ Installation
Stable release
--------------
To install py-polymorphic-loader, run this command in your terminal:
To install polyloader, run this command in your terminal:
.. code-block:: console
$ pip install py-polymorphic-loader
$ pip install polyloader
If you don't have `pip`_ installed, this `Python installation guide`_ can guide
you through the process.
@ -24,19 +24,19 @@ you through the process.
From sources
------------
The sources for py-polymorphic-loader can be downloaded from the `Github repo`_.
The sources for polyloader can be downloaded from the `Github repo`_.
You can either clone the public repository:
.. code-block:: console
$ git clone git://github.com/elfsternberg/py-polymorphic-loader
$ git clone git://github.com/elfsternberg/polyloader
Or download the `tarball`_:
.. code-block:: console
$ curl -OL https://github.com/elfsternberg/py-polymorphic-loader/tarball/master
$ curl -OL https://github.com/elfsternberg/polyloader/tarball/master
Once you have a copy of the source, you can install it with:
@ -45,5 +45,5 @@ Once you have a copy of the source, you can install it with:
$ python setup.py install
.. _Github repo: https://github.com/elfsternberg/py-polymorphic-loader
.. _tarball: https://github.com/elfsternberg/py-polymorphic-loader/tarball/master
.. _Github repo: https://github.com/elfsternberg/polyloader
.. _tarball: https://github.com/elfsternberg/polyloader/tarball/master

View File

@ -1 +1 @@
.. include:: ../README.rst
.. include:: ../../README.rst

View File

@ -2,6 +2,21 @@
Usage
=====
To use py-polymorphic-loader in a project::
Import polyloader in your python script's launcher or library, as well
as the syntax compiler(s) you plan to use. For example, if you have
`Mochi <https://github.com/i2y/mochi>`__ and `Hy
<http://docs.hylang.org/en/latest/>`__ installed, and you wanted to
write a Django app, edit manage.py and add the following lines at the
top:
::
from mochi.main import compile_file as mochi_compile
from hy.importer import ast_compile as hy_compile
import polyloader
polyloader.install(mochi_compile, ['.mochi'])
polyloader.install(hy_compile, ['.hy'])}
Now your views can be written in Hy and your models in Mochi, and
everything will just work.
import py-polymorphic-loader

View File

@ -25,7 +25,7 @@
<script type="text/javascript" src="doctools.js"></script>
<link rel="top" title="polyloader 0.1.0 documentation" href="index.html" />
<link rel="next" title="&lt;no title&gt;" href="authors.html" />
<link rel="prev" title="Usage" href="usage.html" />
<link rel="prev" title="Details on Import and Polyloader" href="details.html" />
</head>
<body>
<div class="related">
@ -41,7 +41,7 @@
<a href="authors.html" title="&lt;no title&gt;"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="usage.html" title="Usage"
<a href="details.html" title="Details on Import and Polyloader"
accesskey="P">previous</a> |</li>
<li><a href="index.html">polyloader 0.1.0 documentation</a> &raquo;</li>
</ul>
@ -60,8 +60,8 @@
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h4>Previous topic</h4>
<p class="topless"><a href="usage.html"
title="previous chapter">Usage</a></p>
<p class="topless"><a href="details.html"
title="previous chapter">Details on Import and Polyloader</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="authors.html"
title="next chapter">&lt;no title&gt;</a></p>
@ -100,7 +100,7 @@
<a href="authors.html" title="&lt;no title&gt;"
>next</a> |</li>
<li class="right" >
<a href="usage.html" title="Usage"
<a href="details.html" title="Details on Import and Polyloader"
>previous</a> |</li>
<li><a href="index.html">polyloader 0.1.0 documentation</a> &raquo;</li>
</ul>

223
docs/details.html Normal file
View File

@ -0,0 +1,223 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Details on Import and Polyloader &mdash; polyloader 0.1.0 documentation</title>
<link rel="stylesheet" href="default.css" type="text/css" />
<link rel="stylesheet" href="pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '0.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="underscore.js"></script>
<script type="text/javascript" src="doctools.js"></script>
<link rel="top" title="polyloader 0.1.0 documentation" href="index.html" />
<link rel="next" title="&lt;no title&gt;" href="contributing.html" />
<link rel="prev" title="Usage" href="usage.html" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="contributing.html" title="&lt;no title&gt;"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="usage.html" title="Usage"
accesskey="P">previous</a> |</li>
<li><a href="index.html">polyloader 0.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="details-on-import-and-polyloader">
<h1>Details on Import and Polyloader<a class="headerlink" href="#details-on-import-and-polyloader" title="Permalink to this headline"></a></h1>
<div class="section" id="welcome-to-the-python-import-eli5">
<h2>Welcome to the Python Import ELI5!<a class="headerlink" href="#welcome-to-the-python-import-eli5" title="Permalink to this headline"></a></h2>
<div class="section" id="what-is-import">
<h3>What is <cite>import</cite>?<a class="headerlink" href="#what-is-import" title="Permalink to this headline"></a></h3>
<p><tt class="docutils literal"><span class="pre">import</span></tt> is a Python statement that finds a <em>module</em> that is accessible
by the currently running process, loads it, and makes its contents
available to the scope in which the statement was made. A statement
like</p>
<p><tt class="docutils literal"><span class="pre">import</span> <span class="pre">django.db.models</span></tt></p>
<p>is looking for a module named <tt class="docutils literal"><span class="pre">django.db.models</span></tt>. If the statement is
successful, <tt class="docutils literal"><span class="pre">django.db.models</span></tt> will be a variable name in the scope,
it will be a Python <em>object</em> (of <tt class="docutils literal"><span class="pre">class</span> <span class="pre">Module</span></tt>, but that&#8217;s not
important), and it will have functions, class constructors, variables
and constants. These Python objects will be accessible through the dot
operator.</p>
<p>An alternative way of writing import statements is</p>
<p><tt class="docutils literal"><span class="pre">from</span> <span class="pre">django.utils</span> <span class="pre">import</span> <span class="pre">encoding</span></tt></p>
<p>And then the variable will just be <tt class="docutils literal"><span class="pre">encoding</span></tt>. The <tt class="docutils literal"><span class="pre">encoding</span></tt>
module has a function for handling unicode-to-web translation.
Accessing it through the dot operator, it looks like this:</p>
<p><tt class="docutils literal"><span class="pre">ready_str</span> <span class="pre">=</span> <span class="pre">encoding.smart_str(unready_str)</span></tt></p>
<p>We call the parts of the import statement that describe the module the
<em>import string</em>.</p>
</div>
<div class="section" id="sys-path-hooks-how-does-python-know-where-to-look">
<h3><tt class="docutils literal"><span class="pre">sys.path_hooks</span></tt>: How does Python know where to look?<a class="headerlink" href="#sys-path-hooks-how-does-python-know-where-to-look" title="Permalink to this headline"></a></h3>
<p>That&#8217;s what&#8217;s funny. Python has two independent ways of making sense of
of the import string. The old system is based on the assumption that
everything is a filesystem, with folders and filenames. This is called
the <tt class="docutils literal"><span class="pre">sys.path_hooks</span></tt> system.</p>
<p>In the old system, the parts of the import string would be split up, and
then a collection of directories would be scanned to see if the first
name in the import string could be matched with a subdirectory. If it
could, that directory would be scanned until the last name on the import
string. If that name was a <em>filename</em>, it would be loaded as a module.
If that name was a <em>directory</em> and that directory had a file named
<tt class="docutils literal"><span class="pre">__init__.py</span></tt>, then that file would be loaded as the module.</p>
<p>The <tt class="docutils literal"><span class="pre">sys.path_hooks</span></tt> array has a list of different methods for trying to
scan a filesystem for the parts of the import string. A <tt class="docutils literal"><span class="pre">path_hook</span></tt> is
a function that takes a path to a directory; if it can handle the
contents of the directory, it returns a <strong>Finder</strong>, an object whose job
is to figure out how to load the module; if it can&#8217;t, it returns an
ImportError exception. The object that loads the module is called,
naturally, a <strong>Loader</strong>.</p>
<ul class="simple">
<li>To read more about <strong>Finders</strong>, see <a class="reference internal" href="eli5.html#eli5-finders"><em>Finders</em></a></li>
<li>To read more about <strong>Loaders</strong>, see <a class="reference internal" href="eli5.html#eli5-loaders"><em>Loaders</em></a></li>
<li>To read more about <strong>Path Hooks</strong>, see <a class="reference internal" href="eli5.html#eli5-pathhooks"><em>Path Hooks</em></a></li>
</ul>
</div>
<div class="section" id="sys-path-what-directories-are-searched">
<h3><tt class="docutils literal"><span class="pre">sys.path</span></tt>: What directories are searched?<a class="headerlink" href="#sys-path-what-directories-are-searched" title="Permalink to this headline"></a></h3>
<p>The list of directories is stored in an array, <tt class="docutils literal"><span class="pre">sys.path</span></tt>. This path is
initialized by Python when it starts up, but programs can modify it at
run-time to point to extra directories if they want.</p>
</div>
<div class="section" id="sys-meta-path-what-is-the-new-system">
<h3><tt class="docutils literal"><span class="pre">sys.meta_path</span></tt>: What is the new system?<a class="headerlink" href="#sys-meta-path-what-is-the-new-system" title="Permalink to this headline"></a></h3>
<p>The new system is called <tt class="docutils literal"><span class="pre">sys.meta_path</span></tt>, and it&#8217;s an array of
<strong>Finders</strong>, objects that have one method, <tt class="docutils literal"><span class="pre">find_module(fullname)</span></tt>.
It&#8217;s an anything-goes API that gives developers the freedom to import
modules from anywhere: databases, archives, remote web resources, even
code written on-the-fly internally. The new system can apply any
meaning at all to the import string.</p>
<p>In Python, the import string is offered to each object in
<tt class="docutils literal"><span class="pre">sys.meta_path</span></tt> before being offered to each <tt class="docutils literal"><span class="pre">sys.path_hook</span></tt>. The
filesystem is typically the last finder tried.</p>
<p>To read more about <strong>Meta Paths</strong>, see <a class="reference internal" href="eli5.html#eli5-metapaths"><em>Meta Paths</em></a></p>
</div>
<div class="section" id="is-it-different-between-python-2-and-python-3">
<h3>Is it different between Python 2 and Python 3?<a class="headerlink" href="#is-it-different-between-python-2-and-python-3" title="Permalink to this headline"></a></h3>
<p>Python 3 moves almost everything about this process into python&#8217;s
library, leaving only a bare minimum of functionality inside the Python
executable to load this library and run it. When the Python developers
did that, they added a lot of functionality to make it easier to write
new import modules. The old way still works, but there are now <em>Module
Specifications</em>, which are metadata about a module, and the old
<tt class="docutils literal"><span class="pre">path_hooks</span></tt> system is now just a <tt class="docutils literal"><span class="pre">meta_path</span></tt> handler added to the
new system as the last resort.</p>
<p>To read more about <strong>Module Specifications</strong>, see <a class="reference internal" href="eli5.html#eli5-specs"><em>Module Specifications</em></a></p>
</div>
<div class="section" id="does-the-old-system-still-matter">
<h3>Does the old system still matter?<a class="headerlink" href="#does-the-old-system-still-matter" title="Permalink to this headline"></a></h3>
<p>Yes, for one reason: <em>iteration</em>. Iteration is the ability to take a
path where you believe Python modules can be found, and list through
them. This facility is useful for large frameworks where a user wants
to add new commands, or new objects, or new operations; Django uses this
facility a lot! The <tt class="docutils literal"><span class="pre">pkgutil</span></tt> library depends upon Finders being able
to iterate their contents.</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Details on Import and Polyloader</a><ul>
<li><a class="reference internal" href="#welcome-to-the-python-import-eli5">Welcome to the Python Import ELI5!</a><ul>
<li><a class="reference internal" href="#what-is-import">What is <cite>import</cite>?</a></li>
<li><a class="reference internal" href="#sys-path-hooks-how-does-python-know-where-to-look"><tt class="docutils literal"><span class="pre">sys.path_hooks</span></tt>: How does Python know where to look?</a></li>
<li><a class="reference internal" href="#sys-path-what-directories-are-searched"><tt class="docutils literal"><span class="pre">sys.path</span></tt>: What directories are searched?</a></li>
<li><a class="reference internal" href="#sys-meta-path-what-is-the-new-system"><tt class="docutils literal"><span class="pre">sys.meta_path</span></tt>: What is the new system?</a></li>
<li><a class="reference internal" href="#is-it-different-between-python-2-and-python-3">Is it different between Python 2 and Python 3?</a></li>
<li><a class="reference internal" href="#does-the-old-system-still-matter">Does the old system still matter?</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="usage.html"
title="previous chapter">Usage</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="contributing.html"
title="next chapter">&lt;no title&gt;</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/details.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="contributing.html" title="&lt;no title&gt;"
>next</a> |</li>
<li class="right" >
<a href="usage.html" title="Usage"
>previous</a> |</li>
<li><a href="index.html">polyloader 0.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2016, Kenneth M. &#34;Elf&#34; Sternberg.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.2.
</div>
</body>
</html>

Binary file not shown.

BIN
docs/doctrees/eli5.doctree Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

126
docs/eli5.html Normal file
View File

@ -0,0 +1,126 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>ELI5: Explain Like Im Five! &mdash; polyloader 0.1.0 documentation</title>
<link rel="stylesheet" href="default.css" type="text/css" />
<link rel="stylesheet" href="pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '0.1.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="underscore.js"></script>
<script type="text/javascript" src="doctools.js"></script>
<link rel="top" title="polyloader 0.1.0 documentation" href="index.html" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li><a href="index.html">polyloader 0.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="eli5-explain-like-i-m-five">
<h1>ELI5: Explain Like I&#8217;m Five!<a class="headerlink" href="#eli5-explain-like-i-m-five" title="Permalink to this headline"></a></h1>
</div>
<div class="section" id="finders">
<span id="eli5-finders"></span><h1>Finders<a class="headerlink" href="#finders" title="Permalink to this headline"></a></h1>
<p>TODO</p>
</div>
<div class="section" id="loaders">
<span id="eli5-loaders"></span><h1>Loaders<a class="headerlink" href="#loaders" title="Permalink to this headline"></a></h1>
<p>TODO</p>
</div>
<div class="section" id="path-hooks">
<span id="eli5-pathhooks"></span><h1>Path Hooks<a class="headerlink" href="#path-hooks" title="Permalink to this headline"></a></h1>
<p>TODO</p>
</div>
<div class="section" id="meta-paths">
<span id="eli5-metapaths"></span><h1>Meta Paths<a class="headerlink" href="#meta-paths" title="Permalink to this headline"></a></h1>
<p>TODO</p>
</div>
<div class="section" id="module-specifications">
<span id="eli5-specs"></span><h1>Module Specifications<a class="headerlink" href="#module-specifications" title="Permalink to this headline"></a></h1>
<p>TODO</p>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">ELI5: Explain Like I&#8217;m Five!</a></li>
<li><a class="reference internal" href="#finders">Finders</a></li>
<li><a class="reference internal" href="#loaders">Loaders</a></li>
<li><a class="reference internal" href="#path-hooks">Path Hooks</a></li>
<li><a class="reference internal" href="#meta-paths">Meta Paths</a></li>
<li><a class="reference internal" href="#module-specifications">Module Specifications</a></li>
</ul>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/eli5.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li><a href="index.html">polyloader 0.1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2016, Kenneth M. &#34;Elf&#34; Sternberg.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.2.
</div>
</body>
</html>

View File

@ -6,7 +6,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Welcome to py-polymorphic-loaders documentation! &mdash; polyloader 0.1.0 documentation</title>
<title>Welcome to polyloader &mdash; polyloader 0.1.0 documentation</title>
<link rel="stylesheet" href="default.css" type="text/css" />
<link rel="stylesheet" href="pygments.css" type="text/css" />
@ -24,7 +24,7 @@
<script type="text/javascript" src="underscore.js"></script>
<script type="text/javascript" src="doctools.js"></script>
<link rel="top" title="polyloader 0.1.0 documentation" href="#" />
<link rel="next" title="&lt;no title&gt;" href="readme.html" />
<link rel="next" title="Synopsis" href="readme.html" />
</head>
<body>
<div class="related">
@ -37,7 +37,7 @@
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="readme.html" title="&lt;no title&gt;"
<a href="readme.html" title="Synopsis"
accesskey="N">next</a> |</li>
<li><a href="#">polyloader 0.1.0 documentation</a> &raquo;</li>
</ul>
@ -48,17 +48,25 @@
<div class="bodywrapper">
<div class="body">
<div class="section" id="welcome-to-py-polymorphic-loader-s-documentation">
<h1>Welcome to py-polymorphic-loader&#8217;s documentation!<a class="headerlink" href="#welcome-to-py-polymorphic-loader-s-documentation" title="Permalink to this headline"></a></h1>
<div class="section" id="welcome-to-polyloader">
<h1>Welcome to polyloader<a class="headerlink" href="#welcome-to-polyloader" title="Permalink to this headline"></a></h1>
<p>Contents:</p>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="readme.html">Synopsis</a></li>
<li class="toctree-l1"><a class="reference internal" href="readme.html#say-what">Say What?</a></li>
<li class="toctree-l1"><a class="reference internal" href="readme.html#what-s-the-real-problem">What&#8217;s the real problem?</a></li>
<li class="toctree-l1"><a class="reference internal" href="readme.html#what-the-solution">What the solution?</a></li>
<li class="toctree-l1"><a class="reference internal" href="installation.html">Installation</a><ul>
<li class="toctree-l2"><a class="reference internal" href="installation.html#stable-release">Stable release</a></li>
<li class="toctree-l2"><a class="reference internal" href="installation.html#from-sources">From sources</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="usage.html">Usage</a></li>
<li class="toctree-l1"><a class="reference internal" href="details.html">Details on Import and Polyloader</a><ul>
<li class="toctree-l2"><a class="reference internal" href="details.html#welcome-to-the-python-import-eli5">Welcome to the Python Import ELI5!</a></li>
</ul>
</li>
</ul>
</div>
</div>
@ -79,13 +87,13 @@
<div class="sphinxsidebarwrapper">
<h3><a href="#">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Welcome to py-polymorphic-loader&#8217;s documentation!</a></li>
<li><a class="reference internal" href="#">Welcome to polyloader</a></li>
<li><a class="reference internal" href="#indices-and-tables">Indices and tables</a></li>
</ul>
<h4>Next topic</h4>
<p class="topless"><a href="readme.html"
title="next chapter">&lt;no title&gt;</a></p>
title="next chapter">Synopsis</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/index.txt"
@ -118,7 +126,7 @@
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="readme.html" title="&lt;no title&gt;"
<a href="readme.html" title="Synopsis"
>next</a> |</li>
<li><a href="#">polyloader 0.1.0 documentation</a> &raquo;</li>
</ul>

View File

@ -25,7 +25,7 @@
<script type="text/javascript" src="doctools.js"></script>
<link rel="top" title="polyloader 0.1.0 documentation" href="index.html" />
<link rel="next" title="Usage" href="usage.html" />
<link rel="prev" title="&lt;no title&gt;" href="readme.html" />
<link rel="prev" title="Synopsis" href="readme.html" />
</head>
<body>
<div class="related">
@ -41,7 +41,7 @@
<a href="usage.html" title="Usage"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="readme.html" title="&lt;no title&gt;"
<a href="readme.html" title="Synopsis"
accesskey="P">previous</a> |</li>
<li><a href="index.html">polyloader 0.1.0 documentation</a> &raquo;</li>
</ul>
@ -56,8 +56,8 @@
<h1>Installation<a class="headerlink" href="#installation" title="Permalink to this headline"></a></h1>
<div class="section" id="stable-release">
<h2>Stable release<a class="headerlink" href="#stable-release" title="Permalink to this headline"></a></h2>
<p>To install py-polymorphic-loader, run this command in your terminal:</p>
<div class="highlight-console"><div class="highlight"><pre><span class="gp">$</span> pip install py-polymorphic-loader
<p>To install polyloader, run this command in your terminal:</p>
<div class="highlight-console"><div class="highlight"><pre><span class="gp">$</span> pip install polyloader
</pre></div>
</div>
<p>If you don&#8217;t have <a class="reference external" href="https://pip.pypa.io">pip</a> installed, this <a class="reference external" href="http://docs.python-guide.org/en/latest/starting/installation/">Python installation guide</a> can guide
@ -65,13 +65,13 @@ you through the process.</p>
</div>
<div class="section" id="from-sources">
<h2>From sources<a class="headerlink" href="#from-sources" title="Permalink to this headline"></a></h2>
<p>The sources for py-polymorphic-loader can be downloaded from the <a class="reference external" href="https://github.com/elfsternberg/py-polymorphic-loader">Github repo</a>.</p>
<p>The sources for polyloader can be downloaded from the <a class="reference external" href="https://github.com/elfsternberg/polyloader">Github repo</a>.</p>
<p>You can either clone the public repository:</p>
<div class="highlight-console"><div class="highlight"><pre><span class="gp">$</span> git clone git://github.com/elfsternberg/py-polymorphic-loader
<div class="highlight-console"><div class="highlight"><pre><span class="gp">$</span> git clone git://github.com/elfsternberg/polyloader
</pre></div>
</div>
<p>Or download the <a class="reference external" href="https://github.com/elfsternberg/py-polymorphic-loader/tarball/master">tarball</a>:</p>
<div class="highlight-console"><div class="highlight"><pre><span class="gp">$</span> curl -OL https://github.com/elfsternberg/py-polymorphic-loader/tarball/master
<p>Or download the <a class="reference external" href="https://github.com/elfsternberg/polyloader/tarball/master">tarball</a>:</p>
<div class="highlight-console"><div class="highlight"><pre><span class="gp">$</span> curl -OL https://github.com/elfsternberg/polyloader/tarball/master
</pre></div>
</div>
<p>Once you have a copy of the source, you can install it with:</p>
@ -98,7 +98,7 @@ you through the process.</p>
<h4>Previous topic</h4>
<p class="topless"><a href="readme.html"
title="previous chapter">&lt;no title&gt;</a></p>
title="previous chapter">Synopsis</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="usage.html"
title="next chapter">Usage</a></p>
@ -137,7 +137,7 @@ you through the process.</p>
<a href="usage.html" title="Usage"
>next</a> |</li>
<li class="right" >
<a href="readme.html" title="&lt;no title&gt;"
<a href="readme.html" title="Synopsis"
>previous</a> |</li>
<li><a href="index.html">polyloader 0.1.0 documentation</a> &raquo;</li>
</ul>

View File

@ -2,6 +2,4 @@
# Project: polyloader
# Version: 0.1.0
# The remainder of this file is compressed using zlib.
xÚŤŽ=
Ă0 F÷śBЬÍšt(z7V<12>l[<5B>ćöm<C3B6>K‡®ď{)°óŃᲸŽě L ójBšIíŕČn!„ÆŞăŹčAKˇjFúé]TV´ł
';b53­ÄÖaşĐ=ą‡'ÖFS<>y)š„eë†%öâ9BűU~$>f±DD7“9h”
<EFBFBD><EFBFBD>Α0 †ο<EΉ<>ΘΑ `4Ρ„„'<27>P`±l„<6C>Dή^fg5ΔΫςχϋΊ¶ j¥+Ό<>uUFς"…&¤Iλ:ΪΐΡΏ#$µµΟ»Δ}…Ρφ D<>©~4ξ'ρ,„ήgS<67>α r(Ϋ¥ΒY  ΟCF®Οsb€ι^Ί¶5ζΊΒη3Ο°<CE9F>΅“^[QΞ3ςπb{,ΧpήΈ<CEAE>)U«R:e΄<65>zC/3<>ΩΒ+f<> "ρf$Ztή«G]ϊ~<7E>~™<1F><>ΦIΆ?¤;<3B>Y½p

View File

@ -6,7 +6,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>&lt;no title&gt; &mdash; polyloader 0.1.0 documentation</title>
<title>Synopsis &mdash; polyloader 0.1.0 documentation</title>
<link rel="stylesheet" href="default.css" type="text/css" />
<link rel="stylesheet" href="pygments.css" type="text/css" />
@ -25,7 +25,7 @@
<script type="text/javascript" src="doctools.js"></script>
<link rel="top" title="polyloader 0.1.0 documentation" href="index.html" />
<link rel="next" title="Installation" href="installation.html" />
<link rel="prev" title="Welcome to py-polymorphic-loaders documentation!" href="index.html" />
<link rel="prev" title="Welcome to polyloader" href="index.html" />
</head>
<body>
<div class="related">
@ -41,7 +41,7 @@
<a href="installation.html" title="Installation"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="index.html" title="Welcome to py-polymorphic-loaders documentation!"
<a href="index.html" title="Welcome to polyloader"
accesskey="P">previous</a> |</li>
<li><a href="index.html">polyloader 0.1.0 documentation</a> &raquo;</li>
</ul>
@ -52,16 +52,80 @@
<div class="bodywrapper">
<div class="body">
<div class="section" id="synopsis">
<h1>Synopsis<a class="headerlink" href="#synopsis" title="Permalink to this headline"></a></h1>
<p><strong>Polyloader</strong> is a python module that extends the Python <cite>import</cite>
statement to enable the discovery and loading of heterogenous source
code packages.</p>
</div>
<div class="section" id="say-what">
<h1>Say What?<a class="headerlink" href="#say-what" title="Permalink to this headline"></a></h1>
<p>The <tt class="docutils literal"><span class="pre">import</span></tt> statement is how the Python interpreter finds a module
written in Python and loads it, turning it into variables, executable
functions, constructable classes, and other Python objects, and then
exposes those objects to the currently running program.</p>
<p>The <tt class="docutils literal"><span class="pre">import</span></tt> statement has long been extensible so that things other
than Python code could be imported, but this feature has always had two
limitations:</p>
<ol class="arabic simple">
<li>It&#8217;s annoyingly hard to write an importer. (Believe me. Polyloader
<em>is</em> one!)</li>
<li>For filesystem-based modules (which is 99% of them) Python&#8217;s importer
only understands one loader type per directory. It&#8217;s not possible to
store code or data written in something other than Python in the same
directory with Python module code and load it via <tt class="docutils literal"><span class="pre">import</span></tt>.</li>
</ol>
<p>The former requires a certain degree of abstraction and thought. For
the latter, most people ignore the problem and load module configuration
files written in JSON or YAML or whatever directly. This is fine,
except when you want to write in one of Python&#8217;s extended languages like
Hy or Coconut in a framework like Django, Flask or Glitch.</p>
<p><strong>Polyloader</strong> eliminates these limitations.</p>
</div>
<div class="section" id="what-s-the-real-problem">
<h1>What&#8217;s the real problem?<a class="headerlink" href="#what-s-the-real-problem" title="Permalink to this headline"></a></h1>
<p>The real problem is that Python&#8217;s traditional extensions, <tt class="docutils literal"><span class="pre">.py</span></tt>,
<tt class="docutils literal"><span class="pre">.pyc/.pyo</span></tt>, and <tt class="docutils literal"><span class="pre">.so/.dll</span></tt> files, are hard-coded in Python. In
Python 2, they&#8217;re in the <tt class="docutils literal"><span class="pre">imp</span></tt> builtin; In Python 3, they&#8217;re defined
in a private section of <cite>importlib</cite>. Either way, they&#8217;re not accessible
for modification and extension.</p>
<p>This problem is made harder by the <tt class="docutils literal"><span class="pre">pkglib</span></tt> module, which is part of
Python&#8217;s standard library. This module uses <tt class="docutils literal"><span class="pre">inspect.getmoduleinfo</span></tt>,
which again only recognizes the usual extensions. Which means you can&#8217;t
list multilingual modules either; this hampers the development of Django
management commands in a syntax other than Python.</p>
</div>
<div class="section" id="what-the-solution">
<h1>What the solution?<a class="headerlink" href="#what-the-solution" title="Permalink to this headline"></a></h1>
<p>At its heart, the Python import system runs two different internal
mechanisms to figure out what the <em>import string</em> (the dotted terms
after the word &#8220;import&#8221;) &#8220;means.&#8221; Each mechanism has one or more
<em>finders</em>, and the first finder to report &#8220;I have a <em>loader</em> that knows
what that import string means&#8221; wins.</p>
<p>The very last finder is for the filesystem. The solution is to get in
front of that finder with one that can handle all the other syntax
loaders <em>and</em> knows how to fall back on the last one for those files the
last one handles.</p>
<p>That&#8217;s what <tt class="docutils literal"><span class="pre">polyloader</span></tt> does.</p>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Synopsis</a></li>
<li><a class="reference internal" href="#say-what">Say What?</a></li>
<li><a class="reference internal" href="#what-s-the-real-problem">What&#8217;s the real problem?</a></li>
<li><a class="reference internal" href="#what-the-solution">What the solution?</a></li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="index.html"
title="previous chapter">Welcome to py-polymorphic-loader&#8217;s documentation!</a></p>
title="previous chapter">Welcome to polyloader</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="installation.html"
title="next chapter">Installation</a></p>
@ -100,7 +164,7 @@
<a href="installation.html" title="Installation"
>next</a> |</li>
<li class="right" >
<a href="index.html" title="Welcome to py-polymorphic-loaders documentation!"
<a href="index.html" title="Welcome to polyloader"
>previous</a> |</li>
<li><a href="index.html">polyloader 0.1.0 documentation</a> &raquo;</li>
</ul>

View File

@ -1 +1 @@
Search.setIndex({envversion:42,terms:{compil:[7,8],set:8,suffix:[7,8],creat:8,process:1,onc:1,modul:[0,2],automat:8,pip:1,through:1,have:1,instal:0,tarbal:1,stabl:0,download:1,guid:1,assum:8,your:1,page:0,index:0,git:1,from:0,activ:8,content:[0,2],leav:8,which:8,master:1,you:1,"public":1,can:1,elfsternberg:1,setup:1,sourc:0,run:[8,1],thi:1,python:[8,1],usag:0,clone:1,copi:1,upon:8,curl:1,standard:8,repo:1,releas:0,mechan:8,repositori:1,termin:1,pair:8,don:1,reset:7,search:0,github:1,last:8,packag:2,remov:8,current:8,http:1,manag:8,project:6,instanc:8,command:1,either:1,context:8,lifetim:8,com:1,scope:8,"import":6},objtypes:{"0":"py:module","1":"py:function"},objnames:{"0":["py","module","Python module"],"1":["py","function","Python function"]},filenames:["index","installation","modules","contributing","readme","authors","usage","polyloader","todo","history"],titles:["Welcome to py-polymorphic-loader&#8217;s documentation!","Installation","polyloader","&lt;no title&gt;","&lt;no title&gt;","&lt;no title&gt;","Usage","polyloader package","&lt;no title&gt;","&lt;no title&gt;"],objects:{"":{polyloader:[7,0,0,"-"]},polyloader:{reset:[7,1,1,""],install:[7,1,1,""]}},titleterms:{polymorph:0,sourc:1,from:1,welcom:0,modul:7,usag:6,indic:0,loader:0,content:7,packag:7,polyload:[7,2],tabl:0,releas:1,stabl:1,document:0,instal:1}})
Search.setIndex({envversion:42,terms:{load:[9,5],all:[9,5],code:[9,5],just:[7,5],move:5,multilingu:9,syntax:[7,9],veri:9,through:[1,5],abil:5,follow:7,discoveri:9,annoyingli:9,find:[9,5],languag:9,suffix:[8,10],access:[9,5],onli:[9,5],depend:5,execut:[9,5],smart_str:5,flask:9,point:5,had:[9,5],except:[9,5],than:9,resort:5,add:[7,5],program:[9,5],those:9,appli:5,reason:5,sens:5,folder:5,main:7,app:7,match:5,take:5,real:0,fly:5,them:[9,5],sourc:0,"return":5,string:[9,5],thei:[9,5],get:9,handl:[9,5],initi:5,util:5,framework:[9,5],ast_compil:7,mechan:[9,10],fall:9,front:9,now:[7,5],archiv:5,requir:9,name:5,tri:5,term:9,like:5,specif:5,hook:5,edit:7,anyth:5,list:[9,5],iter:5,method:5,"try":5,collect:5,either:[9,1],each:[9,5],did:5,unicod:5,page:0,mean:[9,5],compil:[7,8,10],everyth:[7,5],been:9,set:10,natur:5,hard:9,resourc:5,assumpt:5,see:5,meta:5,bare:5,stabl:0,download:1,http:1,fullnam:5,todo:4,hamper:9,librari:[7,9,5],out:[9,5],variabl:[9,5],index:0,insid:5,goe:5,unready_str:5,someth:9,abl:5,per:9,dll:9,current:[9,10,5],figur:[9,5],leav:[10,5],limit:9,content:[0,2,5],"public":1,metadata:5,altern:5,elfsternberg:1,elimin:9,object:[9,5],run:[9,10,1,5],extend:9,web:5,importerror:5,inspect:9,usag:0,privat:9,standard:[9,10],extens:9,job:5,base:[9,5],modif:9,believ:[9,5],repositori:1,found:5,releas:0,from:[0,5],process:[1,5],modifi:5,problem:0,interpret:9,importlib:9,about:5,last:[9,10,5],would:5,befor:5,freedom:5,could:[9,5],success:5,manag:[7,9,10],turn:9,degre:9,instanc:10,context:10,constructor:5,typic:5,view:7,com:1,first:[9,5],oper:5,via:9,user:5,finder:5,directli:9,extra:5,win:9,arrai:5,independ:5,encod:5,pkglib:9,automat:10,loader:5,mochi:7,glitch:9,api:5,yaml:9,latter:9,instal:0,guid:1,facil:5,your:[7,1],git:1,ready_str:5,pkgutil:5,wai:[9,5],script:7,top:7,scan:5,two:[9,5],"long":9,github:1,avail:5,start:5,json:9,handler:5,master:1,statement:[9,5],time:5,call:5,type:9,until:5,store:[9,5],more:[9,5],"function":[9,5],setup:1,lot:5,offer:5,termin:1,peopl:9,copi:1,back:9,remot:5,part:[9,5],understand:9,translat:5,scope:[10,5],line:7,former:9,written:[7,9,5],reset:8,made:[9,5],word:9,describ:5,possibl:9,launcher:7,remov:10,work:[7,5],harder:9,intern:[9,5],can:[7,9,1,5],easier:5,defin:9,"__init__":5,minimum:5,compile_fil:7,whatev:9,assum:10,report:9,modul:5,find_modul:5,heart:9,coconut:9,featur:9,constant:5,file:[9,5],creat:10,give:5,almost:5,certain:9,"abstract":9,filenam:5,ani:5,activ:10,packag:2,pip:1,hy_compil:7,have:[7,9,1,5],tarbal:1,synopsi:0,curl:1,sai:0,getmoduleinfo:9,alwai:9,develop:[9,5],want:[7,9,5],thing:9,make:5,expos:9,when:[9,5],same:9,write:[7,9,5],funni:5,builtin:9,other:9,read:5,split:5,which:[9,10,5],subdirectori:5,command:[9,1,5],you:[7,9,1,5],mochi_compil:7,enabl:9,even:5,imp:9,recogn:9,again:9,configur:9,clone:1,after:9,upon:[10,5],solut:0,most:9,larg:5,plan:7,pyo:9,pair:10,construct:9,pyc:9,data:9,"class":[9,5],tradit:9,repo:1,lifetim:10,don:1,whose:5,filesystem:[9,5],anywher:5,well:7,fine:9,django:[7,9,5],thought:9,heterogen:9,exampl:7,ignor:9,thi:[9,1,5],databas:5,onc:1,model:[7,5],section:9,dot:[9,5],usual:9},objtypes:{"0":"py:module","1":"py:function"},objnames:{"0":["py","module","Python module"],"1":["py","function","Python function"]},filenames:["index","installation","modules","contributing","eli5","details","authors","usage","polyloader","readme","todo","history"],titles:["Welcome to polyloader","Installation","polyloader","&lt;no title&gt;","ELI5: Explain Like I&#8217;m Five!","Details on Import and Polyloader","&lt;no title&gt;","Usage","polyloader package","Synopsis","&lt;no title&gt;","&lt;no title&gt;"],objects:{"":{polyloader:[8,0,0,"-"]},polyloader:{reset:[8,1,1,""],install:[8,1,1,""]}},titleterms:{sai:9,old:5,modul:[4,8],meta_path:5,system:5,hook:4,meta:4,tabl:0,stabl:1,still:5,what:[9,5],from:1,welcom:[0,5],explain:4,solut:9,detail:5,content:8,how:5,between:5,"new":5,instal:1,finder:4,real:9,sourc:1,synopsi:9,python:5,usag:7,differ:5,eli5:[4,5],path_hook:5,indic:0,"import":5,releas:1,path:[4,5],loader:4,look:5,search:5,like:4,specif:4,packag:8,directori:5,doe:5,matter:5,polyload:[0,2,5,8],five:4,problem:9,where:5,know:5}})

111
docs/src/details.rst Normal file
View File

@ -0,0 +1,111 @@
Details on Import and Polyloader
================================
Welcome to the Python Import ELI5!
**********************************
What is `import`?
-----------------
``import`` is a Python statement that finds a *module* that is accessible
by the currently running process, loads it, and makes its contents
available to the scope in which the statement was made. A statement
like
``import django.db.models``
is looking for a module named ``django.db.models``. If the statement is
successful, ``django.db.models`` will be a variable name in the scope,
it will be a Python *object* (of ``class Module``, but that's not
important), and it will have functions, class constructors, variables
and constants. These Python objects will be accessible through the dot
operator.
An alternative way of writing import statements is
``from django.utils import encoding``
And then the variable will just be ``encoding``. The ``encoding``
module has a function for handling unicode-to-web translation.
Accessing it through the dot operator, it looks like this:
``ready_str = encoding.smart_str(unready_str)``
We call the parts of the import statement that describe the module the
*import string*.
``sys.path_hooks``: How does Python know where to look?
-------------------------------------------------------
That's what's funny. Python has two independent ways of making sense of
of the import string. The old system is based on the assumption that
everything is a filesystem, with folders and filenames. This is called
the ``sys.path_hooks`` system.
In the old system, the parts of the import string would be split up, and
then a collection of directories would be scanned to see if the first
name in the import string could be matched with a subdirectory. If it
could, that directory would be scanned until the last name on the import
string. If that name was a *filename*, it would be loaded as a module.
If that name was a *directory* and that directory had a file named
``__init__.py``, then that file would be loaded as the module.
The ``sys.path_hooks`` array has a list of different methods for trying to
scan a filesystem for the parts of the import string. A ``path_hook`` is
a function that takes a path to a directory; if it can handle the
contents of the directory, it returns a **Finder**, an object whose job
is to figure out how to load the module; if it can't, it returns an
ImportError exception. The object that loads the module is called,
naturally, a **Loader**.
* To read more about **Finders**, see :ref:`eli5-finders`
* To read more about **Loaders**, see :ref:`eli5-loaders`
* To read more about **Path Hooks**, see :ref:`eli5-pathhooks`
``sys.path``: What directories are searched?
--------------------------------------------
The list of directories is stored in an array, ``sys.path``. This path is
initialized by Python when it starts up, but programs can modify it at
run-time to point to extra directories if they want.
``sys.meta_path``: What is the new system?
------------------------------------------
The new system is called ``sys.meta_path``, and it's an array of
**Finders**, objects that have one method, ``find_module(fullname)``.
It's an anything-goes API that gives developers the freedom to import
modules from anywhere: databases, archives, remote web resources, even
code written on-the-fly internally. The new system can apply any
meaning at all to the import string.
In Python, the import string is offered to each object in
``sys.meta_path`` before being offered to each ``sys.path_hook``. The
filesystem is typically the last finder tried.
To read more about **Meta Paths**, see :ref:`eli5-metapaths`
Is it different between Python 2 and Python 3?
---------------------------------------------
Python 3 moves almost everything about this process into python's
library, leaving only a bare minimum of functionality inside the Python
executable to load this library and run it. When the Python developers
did that, they added a lot of functionality to make it easier to write
new import modules. The old way still works, but there are now *Module
Specifications*, which are metadata about a module, and the old
``path_hooks`` system is now just a ``meta_path`` handler added to the
new system as the last resort.
To read more about **Module Specifications**, see :ref:`eli5-specs`
Does the old system still matter?
---------------------------------
Yes, for one reason: *iteration*. Iteration is the ability to take a
path where you believe Python modules can be found, and list through
them. This facility is useful for large frameworks where a user wants
to add new commands, or new objects, or new operations; Django uses this
facility a lot! The ``pkgutil`` library depends upon Finders being able
to iterate their contents.

37
docs/src/eli5.rst Normal file
View File

@ -0,0 +1,37 @@
ELI5: Explain Like I'm Five!
============================
.. _eli5-finders:
Finders
=======
TODO
.. _eli5-loaders:
Loaders
=======
TODO
.. _eli5-pathhooks:
Path Hooks
==========
TODO
.. _eli5-metapaths:
Meta Paths
==========
TODO
.. _eli5-specs:
Module Specifications
=====================
TODO

View File

@ -3,8 +3,8 @@
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to py-polymorphic-loader's documentation!
======================================
Welcome to polyloader
=====================
Contents:
@ -14,6 +14,7 @@ Contents:
readme
installation
usage
details
contributing
authors
history

View File

@ -8,11 +8,11 @@ Installation
Stable release
--------------
To install py-polymorphic-loader, run this command in your terminal:
To install polyloader, run this command in your terminal:
.. code-block:: console
$ pip install py-polymorphic-loader
$ pip install polyloader
If you don't have `pip`_ installed, this `Python installation guide`_ can guide
you through the process.
@ -24,19 +24,19 @@ you through the process.
From sources
------------
The sources for py-polymorphic-loader can be downloaded from the `Github repo`_.
The sources for polyloader can be downloaded from the `Github repo`_.
You can either clone the public repository:
.. code-block:: console
$ git clone git://github.com/elfsternberg/py-polymorphic-loader
$ git clone git://github.com/elfsternberg/polyloader
Or download the `tarball`_:
.. code-block:: console
$ curl -OL https://github.com/elfsternberg/py-polymorphic-loader/tarball/master
$ curl -OL https://github.com/elfsternberg/polyloader/tarball/master
Once you have a copy of the source, you can install it with:
@ -45,5 +45,5 @@ Once you have a copy of the source, you can install it with:
$ python setup.py install
.. _Github repo: https://github.com/elfsternberg/py-polymorphic-loader
.. _tarball: https://github.com/elfsternberg/py-polymorphic-loader/tarball/master
.. _Github repo: https://github.com/elfsternberg/polyloader
.. _tarball: https://github.com/elfsternberg/polyloader/tarball/master

View File

@ -1 +1 @@
.. include:: ../README.rst
.. include:: ../../README.rst

View File

@ -2,6 +2,21 @@
Usage
=====
To use py-polymorphic-loader in a project::
Import polyloader in your python script's launcher or library, as well
as the syntax compiler(s) you plan to use. For example, if you have
`Mochi <https://github.com/i2y/mochi>`__ and `Hy
<http://docs.hylang.org/en/latest/>`__ installed, and you wanted to
write a Django app, edit manage.py and add the following lines at the
top:
::
from mochi.main import compile_file as mochi_compile
from hy.importer import ast_compile as hy_compile
import polyloader
polyloader.install(mochi_compile, ['.mochi'])
polyloader.install(hy_compile, ['.hy'])}
Now your views can be written in Hy and your models in Mochi, and
everything will just work.
import py-polymorphic-loader

View File

@ -24,7 +24,7 @@
<script type="text/javascript" src="underscore.js"></script>
<script type="text/javascript" src="doctools.js"></script>
<link rel="top" title="polyloader 0.1.0 documentation" href="index.html" />
<link rel="next" title="&lt;no title&gt;" href="contributing.html" />
<link rel="next" title="Details on Import and Polyloader" href="details.html" />
<link rel="prev" title="Installation" href="installation.html" />
</head>
<body>
@ -38,7 +38,7 @@
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="contributing.html" title="&lt;no title&gt;"
<a href="details.html" title="Details on Import and Polyloader"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="installation.html" title="Installation"
@ -54,10 +54,20 @@
<div class="section" id="usage">
<h1>Usage<a class="headerlink" href="#usage" title="Permalink to this headline"></a></h1>
<p>To use py-polymorphic-loader in a project:</p>
<div class="highlight-python"><div class="highlight"><pre>import py-polymorphic-loader
<p>Import polyloader in your python script&#8217;s launcher or library, as well
as the syntax compiler(s) you plan to use. For example, if you have
<a class="reference external" href="https://github.com/i2y/mochi">Mochi</a> and <a class="reference external" href="http://docs.hylang.org/en/latest/">Hy</a> installed, and you wanted to
write a Django app, edit manage.py and add the following lines at the
top:</p>
<div class="highlight-python"><div class="highlight"><pre>from mochi.main import compile_file as mochi_compile
from hy.importer import ast_compile as hy_compile
import polyloader
polyloader.install(mochi_compile, [&#39;.mochi&#39;])
polyloader.install(hy_compile, [&#39;.hy&#39;])}
</pre></div>
</div>
<p>Now your views can be written in Hy and your models in Mochi, and
everything will just work.</p>
</div>
@ -70,8 +80,8 @@
<p class="topless"><a href="installation.html"
title="previous chapter">Installation</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="contributing.html"
title="next chapter">&lt;no title&gt;</a></p>
<p class="topless"><a href="details.html"
title="next chapter">Details on Import and Polyloader</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/usage.txt"
@ -104,7 +114,7 @@
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="contributing.html" title="&lt;no title&gt;"
<a href="details.html" title="Details on Import and Polyloader"
>next</a> |</li>
<li class="right" >
<a href="installation.html" title="Installation"