Skip to content

Commit

Permalink
Fix #41 (#104)
Browse files Browse the repository at this point in the history
  • Loading branch information
Rodrigo Martins de Oliveira committed Aug 15, 2021
1 parent 6d3917e commit 0c5d777
Show file tree
Hide file tree
Showing 53 changed files with 595 additions and 221 deletions.
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 3.4.6
current_version = 3.4.7

[bumpversion:file:Makefile]
search = CURRENT_VERSION = {current_version}
Expand Down
39 changes: 39 additions & 0 deletions CAVEATS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
=======
Caveats
=======

This is a non-exhaustive list of known caveats to the usage of this library.

Automatic dependency discovery
------------------------------

Injectable automatic dependency discovery system is inspired from Airflow's DAG automatic
discovery. So first all files in the search path are recursively read looking for any
occurrence of the following four strings: ``@injectable``, ``injectable(``,
``@injectable_factory``, and ``injectable_factory(``. Then those files are executed as
python modules so the decorators can register the injectable to the container.

This implementation leads to some issues:

* If, for any reason, the code aliases the decorators to other incompatible names or
do not use the decorator functions directly automatic dependency will fail and those
injectables will never be registered to the container.
* Any file containing these strings will be executed causing potential unintended
side-effects such as file-level code outside classes and functions being executed.
* The module of each injectable class may be loaded twice: one for in this automatic
discovery step and another by the regular application operation. This will render
impossible to run type checks for injected objects through the use of ``type`` or
``isinstance`` builtin functions. If one must type check using the type's
``__qualname__`` attribute is a possible workaround.

Pytest and relative imports
---------------------------

As described in this issue: https://github.com/pytest-dev/pytest/issues/9007 , pytest
won't work with injectable's automatic dependency discovery system if one declares
injectables in the same file of the test itself, load the injection container during the
test and use relative imports in this file. This corner-case combination will lead to an
``AttributeError: 'AssertionRewritingHook' object has no attribute 'get_code'``.

Currently the workaround for this is either to use absolute imports in these files or to
move the declaration of injectables to any other file other than the test's file.
21 changes: 13 additions & 8 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
Changelog
=========

3.4.7 (2021-08-15)
------------------

* Fix injectable crashing when relative imports are used in files containing injectables.

3.4.6 (2021-03-20)
------------------

* Fix ``testing.register_injectables`` not creating the namespace when it doesn't exist
yet
yet

3.4.5 (2021-03-11)
------------------
Expand Down Expand Up @@ -50,7 +55,7 @@ Changelog
------------------

* ``InjectionContainer::load`` is more resilient against duplicated injectables
registering
registering

3.2.0 (2020-04-15)
------------------
Expand All @@ -76,7 +81,7 @@ Changelog
------------------

* Fix bug of scanning the same module more than once when ``InjectionContainer.load()``
is called multiple times with different relative search paths.
is called multiple times with different relative search paths.

3.1.0 (2020-04-13)
------------------
Expand Down Expand Up @@ -121,11 +126,11 @@ Changelog
------------------

* Statically infer dependency's constructor suitability for injection instead of using
trial instantiation
trial instantiation
* Fix bug of raising ``TypeError`` when injectable fails on the trial dependency
instantiation which can happen when the dependency does provide a default
constructor with no arguments but the running environment (possibly a test suite
environment) will make the instantiation fail
instantiation which can happen when the dependency does provide a default
constructor with no arguments but the running environment (possibly a test suite
environment) will make the instantiation fail

1.1.0 (2018-02-10)
------------------
Expand All @@ -136,7 +141,7 @@ Changelog
------------------

* Fixes required dependency ``lazy_object_proxy`` not being installed when installing
injectable through pip
injectable through pip

1.0.0 (2018-02-06)
------------------
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ docs:
make html -B
cp -a build/html/. docs

CURRENT_VERSION = 3.4.6
CURRENT_VERSION = 3.4.7

.PHONY: bump-patch-version
bump-patch-version:
Expand Down
2 changes: 1 addition & 1 deletion docs/.buildinfo
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config: 1713a5b2b0df61545c670b29a0cc2394
config: 608fa2521195fa2771065e2da377c1f9
tags: 645f666f9bcd5a90fca523b33c5a78b7
7 changes: 4 additions & 3 deletions docs/_modules/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Overview: module code &#8212; injectable 3.4.6 documentation</title>
<title>Overview: module code &#8212; injectable 3.4.7 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pydoctheme.css" />

Expand All @@ -28,7 +28,7 @@
<h3>Navigation</h3>
<ul>
<li class="responsive-menu"><a href="#sidebar-anchor" title="Navigation">&#9776;</a></li>
<li><a href="../index.html">injectable-3.4.6</a> &#187;</li>
<li><a href="../index.html">injectable-3.4.7</a> &#187;</li>
</ul>
</div>

Expand Down Expand Up @@ -84,6 +84,7 @@ <h3 id="searchlabel">Quick search</h3>
<li class="toctree-l1"><a class="reference internal" href="../installation.html">Installation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../usage/index.html">Usage Examples</a></li>
<li class="toctree-l1"><a class="reference internal" href="../reference/index.html">Reference</a></li>
<li class="toctree-l1"><a class="reference internal" href="../caveats.html">Caveats</a></li>
<li class="toctree-l1"><a class="reference internal" href="../contributing.html">Contributing</a></li>
<li class="toctree-l1"><a class="reference internal" href="../authors.html">Authors</a></li>
<li class="toctree-l1"><a class="reference internal" href="../changelog.html">Changelog</a></li>
Expand All @@ -107,7 +108,7 @@ <h3>Navigation</h3>

<div class="footer" role="contentinfo">
&#169; Copyright 2018, Rodrigo Martins de Oliveira.
Last updated on Aug 14, 2021.
Last updated on Aug 15, 2021.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 4.1.2.
</div>
</body>
Expand Down
24 changes: 17 additions & 7 deletions docs/_modules/injectable/container/injection_container.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>injectable.container.injection_container &#8212; injectable 3.4.6 documentation</title>
<title>injectable.container.injection_container &#8212; injectable 3.4.7 documentation</title>
<link rel="stylesheet" type="text/css" href="../../../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../../../_static/pydoctheme.css" />

Expand All @@ -28,7 +28,7 @@
<h3>Navigation</h3>
<ul>
<li class="responsive-menu"><a href="#sidebar-anchor" title="Navigation">&#9776;</a></li>
<li><a href="../../../index.html">injectable-3.4.6</a> &#187;</li>
<li><a href="../../../index.html">injectable-3.4.7</a> &#187;</li>
<li><a href="../../index.html" accesskey="U">Module code</a> &#187;</li>
</ul>
</div>
Expand All @@ -48,11 +48,11 @@ <h3>Navigation</h3>
<h1>Source code for injectable.container.injection_container</h1><div class="highlight"><pre>
<span></span><span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">warnings</span>
<span class="kn">from</span> <span class="nn">runpy</span> <span class="kn">import</span> <span class="n">run_path</span>
<span class="kn">from</span> <span class="nn">runpy</span> <span class="kn">import</span> <span class="n">run_path</span><span class="p">,</span> <span class="n">run_module</span>
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Dict</span><span class="p">,</span> <span class="n">Optional</span><span class="p">,</span> <span class="n">Callable</span>
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Set</span>

<span class="kn">from</span> <span class="nn">pycollect</span> <span class="kn">import</span> <span class="n">PythonFileCollector</span>
<span class="kn">from</span> <span class="nn">pycollect</span> <span class="kn">import</span> <span class="n">PythonFileCollector</span><span class="p">,</span> <span class="n">module_finder</span>

<span class="kn">from</span> <span class="nn">injectable.container.injectable</span> <span class="kn">import</span> <span class="n">Injectable</span>
<span class="kn">from</span> <span class="nn">injectable.container.namespace</span> <span class="kn">import</span> <span class="n">Namespace</span>
Expand Down Expand Up @@ -193,7 +193,12 @@ <h1>Source code for injectable.container.injection_container</h1><div class="hig
<span class="k">if</span> <span class="n">file</span><span class="o">.</span><span class="n">path</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">LOADED_FILEPATHS</span><span class="p">:</span>
<span class="k">continue</span>
<span class="bp">cls</span><span class="o">.</span><span class="n">LOADING_FILEPATH</span> <span class="o">=</span> <span class="n">file</span><span class="o">.</span><span class="n">path</span>
<span class="n">run_path</span><span class="p">(</span><span class="n">file</span><span class="o">.</span><span class="n">path</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">run_module</span><span class="p">(</span><span class="n">module_finder</span><span class="o">.</span><span class="n">find_module_name</span><span class="p">(</span><span class="n">file</span><span class="o">.</span><span class="n">path</span><span class="p">))</span>
<span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
<span class="c1"># This is needed for some corner cases involving pytest</span>
<span class="c1"># See more at https://github.com/pytest-dev/pytest/issues/9007</span>
<span class="n">run_path</span><span class="p">(</span><span class="n">file</span><span class="o">.</span><span class="n">path</span><span class="p">)</span>
<span class="bp">cls</span><span class="o">.</span><span class="n">LOADED_FILEPATHS</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">file</span><span class="o">.</span><span class="n">path</span><span class="p">)</span>
<span class="bp">cls</span><span class="o">.</span><span class="n">LOADING_FILEPATH</span> <span class="o">=</span> <span class="kc">None</span>

Expand All @@ -211,7 +216,12 @@ <h1>Source code for injectable.container.injection_container</h1><div class="hig
<span class="k">if</span> <span class="n">file</span><span class="o">.</span><span class="n">path</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">LOADED_FILEPATHS</span><span class="p">:</span>
<span class="k">continue</span>
<span class="bp">cls</span><span class="o">.</span><span class="n">LOADING_FILEPATH</span> <span class="o">=</span> <span class="n">file</span><span class="o">.</span><span class="n">path</span>
<span class="n">run_path</span><span class="p">(</span><span class="n">file</span><span class="o">.</span><span class="n">path</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">run_module</span><span class="p">(</span><span class="n">module_finder</span><span class="o">.</span><span class="n">find_module_name</span><span class="p">(</span><span class="n">file</span><span class="o">.</span><span class="n">path</span><span class="p">))</span>
<span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
<span class="c1"># This is needed for some corner cases involving pytest</span>
<span class="c1"># See more at https://github.com/pytest-dev/pytest/issues/9007</span>
<span class="n">run_path</span><span class="p">(</span><span class="n">file</span><span class="o">.</span><span class="n">path</span><span class="p">)</span>
<span class="bp">cls</span><span class="o">.</span><span class="n">LOADED_FILEPATHS</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">file</span><span class="o">.</span><span class="n">path</span><span class="p">)</span>
<span class="bp">cls</span><span class="o">.</span><span class="n">LOADING_FILEPATH</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">cls</span><span class="o">.</span><span class="n">LOADING_DEFAULT_NAMESPACE</span> <span class="o">=</span> <span class="kc">None</span>
Expand Down Expand Up @@ -284,7 +294,7 @@ <h3>Navigation</h3>

<div class="footer" role="contentinfo">
&#169; Copyright 2018, Rodrigo Martins de Oliveira.
Last updated on Aug 14, 2021.
Last updated on Aug 15, 2021.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 4.1.2.
</div>
</body>
Expand Down
1 change: 1 addition & 0 deletions docs/_sources/caveats.rst.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.. include:: ../CAVEATS.rst
1 change: 1 addition & 0 deletions docs/_sources/index.rst.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Contents
installation
usage/index
reference/index
caveats
contributing
authors
changelog
Expand Down
2 changes: 1 addition & 1 deletion docs/_static/documentation_options.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
var DOCUMENTATION_OPTIONS = {
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
VERSION: '3.4.6',
VERSION: '3.4.7',
LANGUAGE: 'None',
COLLAPSE_INDEX: false,
BUILDER: 'html',
Expand Down
7 changes: 4 additions & 3 deletions docs/authors.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Authors &#8212; injectable 3.4.6 documentation</title>
<title>Authors &#8212; injectable 3.4.7 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/pydoctheme.css" />

Expand All @@ -30,7 +30,7 @@
<h3>Navigation</h3>
<ul>
<li class="responsive-menu"><a href="#sidebar-anchor" title="Navigation">&#9776;</a></li>
<li><a href="index.html">injectable-3.4.6</a> &#187;</li>
<li><a href="index.html">injectable-3.4.7</a> &#187;</li>
</ul>
</div>

Expand Down Expand Up @@ -80,6 +80,7 @@ <h3 id="searchlabel">Quick search</h3>
<li class="toctree-l1"><a class="reference internal" href="installation.html">Installation</a></li>
<li class="toctree-l1"><a class="reference internal" href="usage/index.html">Usage Examples</a></li>
<li class="toctree-l1"><a class="reference internal" href="reference/index.html">Reference</a></li>
<li class="toctree-l1"><a class="reference internal" href="caveats.html">Caveats</a></li>
<li class="toctree-l1"><a class="reference internal" href="contributing.html">Contributing</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">Authors</a></li>
<li class="toctree-l1"><a class="reference internal" href="changelog.html">Changelog</a></li>
Expand Down Expand Up @@ -116,7 +117,7 @@ <h3>Navigation</h3>

<div class="footer" role="contentinfo">
&#169; Copyright 2018, Rodrigo Martins de Oliveira.
Last updated on Aug 14, 2021.
Last updated on Aug 15, 2021.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 4.1.2.
</div>
</body>
Expand Down
Loading

0 comments on commit 0c5d777

Please sign in to comment.