mirror of
https://github.com/evennia/evennia.git
synced 2026-03-20 06:46:31 +01:00
859 lines
No EOL
98 KiB
HTML
859 lines
No EOL
98 KiB
HTML
|
|
<!DOCTYPE html>
|
|
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>parameterized.parameterized — Evennia latest documentation</title>
|
|
<link rel="stylesheet" href="../../_static/nature.css" type="text/css" />
|
|
<link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
|
|
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css?v=d75fae25" />
|
|
<link rel="stylesheet" type="text/css" href="../../_static/nature.css?v=245aff17" />
|
|
<script id="documentation_options" data-url_root="../../" src="../../_static/documentation_options.js"></script>
|
|
<script src="../../_static/documentation_options.js?v=c6e86fd7"></script>
|
|
<script src="../../_static/doctools.js?v=9bcbadda"></script>
|
|
<script src="../../_static/sphinx_highlight.js?v=dc90522c"></script>
|
|
<link rel="index" title="Index" href="../../genindex.html" />
|
|
<link rel="search" title="Search" href="../../search.html" />
|
|
</head><body>
|
|
|
|
|
|
|
|
|
|
<div class="related" role="navigation" aria-label="related navigation">
|
|
<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="nav-item nav-item-0"><a href="../../index.html">Evennia latest</a> »</li>
|
|
<li class="nav-item nav-item-1"><a href="../index.html" accesskey="U">Module code</a> »</li>
|
|
<li class="nav-item nav-item-this"><a href="">parameterized.parameterized</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="document">
|
|
|
|
<div class="documentwrapper">
|
|
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
|
<div class="sphinxsidebarwrapper">
|
|
<search id="searchbox" style="display: none" role="search">
|
|
<h3 id="searchlabel">Quick search</h3>
|
|
<div class="searchformwrapper">
|
|
<form class="search" action="../../search.html" method="get">
|
|
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
|
<input type="submit" value="Go" />
|
|
</form>
|
|
</div>
|
|
</search>
|
|
<script>document.getElementById('searchbox').style.display = "block"</script><h3>Links</h3>
|
|
<ul>
|
|
<li><a href="https://www.evennia.com/docs/latest/index.html">Documentation Top</a> </li>
|
|
<li><a href="https://www.evennia.com">Evennia Home</a> </li>
|
|
<li><a href="https://github.com/evennia/evennia">Github</a> </li>
|
|
<li><a href="http://games.evennia.com">Game Index</a> </li>
|
|
<li>
|
|
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
|
|
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
|
|
<a href="https://evennia.blogspot.com/">Blog</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="bodywrapper">
|
|
<div class="body" role="main">
|
|
|
|
<h1>Source code for parameterized.parameterized</h1><div class="highlight"><pre>
|
|
<span></span><span class="kn">import</span><span class="w"> </span><span class="nn">re</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">inspect</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">warnings</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Iterable</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">functools</span><span class="w"> </span><span class="kn">import</span> <span class="n">wraps</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">types</span><span class="w"> </span><span class="kn">import</span> <span class="n">MethodType</span> <span class="k">as</span> <span class="n">MethodType</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">collections</span><span class="w"> </span><span class="kn">import</span> <span class="n">namedtuple</span>
|
|
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">unittest</span><span class="w"> </span><span class="kn">import</span> <span class="n">mock</span>
|
|
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">mock</span>
|
|
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
|
|
<span class="n">mock</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">collections</span><span class="w"> </span><span class="kn">import</span> <span class="n">OrderedDict</span> <span class="k">as</span> <span class="n">MaybeOrderedDict</span>
|
|
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
|
|
<span class="n">MaybeOrderedDict</span> <span class="o">=</span> <span class="nb">dict</span>
|
|
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">unittest</span><span class="w"> </span><span class="kn">import</span> <span class="n">TestCase</span>
|
|
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">unittest</span><span class="w"> </span><span class="kn">import</span> <span class="n">SkipTest</span>
|
|
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">SkipTest</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
|
|
<span class="k">pass</span>
|
|
|
|
<span class="c1"># NOTE: even though Python 2 support has been dropped, these checks have been</span>
|
|
<span class="c1"># left in place to avoid merge conflicts. They can be removed in the future, and</span>
|
|
<span class="c1"># future code can be written to assume Python 3.</span>
|
|
<span class="n">PY3</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">version_info</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="mi">3</span>
|
|
<span class="n">PY2</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">version_info</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="mi">2</span>
|
|
|
|
|
|
<span class="k">if</span> <span class="n">PY3</span><span class="p">:</span>
|
|
<span class="c1"># Python 3 doesn't have an InstanceType, so just use a dummy type.</span>
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">InstanceType</span><span class="p">():</span>
|
|
<span class="k">pass</span>
|
|
<span class="n">lzip</span> <span class="o">=</span> <span class="k">lambda</span> <span class="o">*</span><span class="n">a</span><span class="p">:</span> <span class="nb">list</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">))</span>
|
|
<span class="n">text_type</span> <span class="o">=</span> <span class="nb">str</span>
|
|
<span class="n">string_types</span> <span class="o">=</span> <span class="nb">str</span><span class="p">,</span>
|
|
<span class="n">bytes_type</span> <span class="o">=</span> <span class="nb">bytes</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">make_method</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">instance</span><span class="p">,</span> <span class="nb">type</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">instance</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">func</span>
|
|
<span class="k">return</span> <span class="n">MethodType</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">instance</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">types</span><span class="w"> </span><span class="kn">import</span> <span class="n">InstanceType</span>
|
|
<span class="n">lzip</span> <span class="o">=</span> <span class="nb">zip</span>
|
|
<span class="n">text_type</span> <span class="o">=</span> <span class="n">unicode</span>
|
|
<span class="n">bytes_type</span> <span class="o">=</span> <span class="nb">str</span>
|
|
<span class="n">string_types</span> <span class="o">=</span> <span class="n">basestring</span><span class="p">,</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">make_method</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">instance</span><span class="p">,</span> <span class="nb">type</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="n">MethodType</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">instance</span><span class="p">,</span> <span class="nb">type</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">to_text</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">text_type</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="n">x</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">text_type</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="s2">"utf-8"</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">UnicodeDecodeError</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">text_type</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="s2">"latin1"</span><span class="p">)</span>
|
|
|
|
<span class="n">CompatArgSpec</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s2">"CompatArgSpec"</span><span class="p">,</span> <span class="s2">"args varargs keywords defaults"</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">getargspec</span><span class="p">(</span><span class="n">func</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">PY2</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">CompatArgSpec</span><span class="p">(</span><span class="o">*</span><span class="n">inspect</span><span class="o">.</span><span class="n">getargspec</span><span class="p">(</span><span class="n">func</span><span class="p">))</span>
|
|
<span class="n">args</span> <span class="o">=</span> <span class="n">inspect</span><span class="o">.</span><span class="n">getfullargspec</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">kwonlyargs</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">((</span>
|
|
<span class="s2">"parameterized does not (yet) support functions with keyword "</span>
|
|
<span class="s2">"only arguments, but </span><span class="si">%r</span><span class="s2"> has keyword only arguments. "</span>
|
|
<span class="s2">"Please open an issue with your usecase if this affects you: "</span>
|
|
<span class="s2">"https://github.com/wolever/parameterized/issues/new"</span>
|
|
<span class="p">)</span> <span class="o">%</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="p">))</span>
|
|
<span class="k">return</span> <span class="n">CompatArgSpec</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">[:</span><span class="mi">4</span><span class="p">])</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">skip_on_empty_helper</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="n">SkipTest</span><span class="p">(</span><span class="s2">"parameterized input is empty"</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">reapply_patches_if_need</span><span class="p">(</span><span class="n">func</span><span class="p">):</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">dummy_wrapper</span><span class="p">(</span><span class="n">orgfunc</span><span class="p">):</span>
|
|
<span class="nd">@wraps</span><span class="p">(</span><span class="n">orgfunc</span><span class="p">)</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">dummy_func</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="n">orgfunc</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">dummy_func</span>
|
|
|
|
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="s1">'patchings'</span><span class="p">):</span>
|
|
<span class="n">is_original_async</span> <span class="o">=</span> <span class="n">inspect</span><span class="o">.</span><span class="n">iscoroutinefunction</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
|
|
<span class="n">func</span> <span class="o">=</span> <span class="n">dummy_wrapper</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
|
|
<span class="n">tmp_patchings</span> <span class="o">=</span> <span class="n">func</span><span class="o">.</span><span class="n">patchings</span>
|
|
<span class="nb">delattr</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="s1">'patchings'</span><span class="p">)</span>
|
|
<span class="k">for</span> <span class="n">patch_obj</span> <span class="ow">in</span> <span class="n">tmp_patchings</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">is_original_async</span><span class="p">:</span>
|
|
<span class="n">func</span> <span class="o">=</span> <span class="n">patch_obj</span><span class="o">.</span><span class="n">decorate_async_callable</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">func</span> <span class="o">=</span> <span class="n">patch_obj</span><span class="o">.</span><span class="n">decorate_callable</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">func</span>
|
|
|
|
|
|
<span class="c1"># `parameterized.expand` strips out `mock` patches from the source method in favor of re-applying them over the</span>
|
|
<span class="c1"># generated methods instead. Sadly, this can cause problems with old versions of the `mock` package, as shown in</span>
|
|
<span class="c1"># https://bugs.python.org/issue40126 (bpo-40126).</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># Long story short, bpo-40126 arises whenever the `patchings` list of a `mock`-decorated method is left fully empty.</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># The bug has been fixed in the `mock` code itself since:</span>
|
|
<span class="c1"># - Python 3.7.8-rc1, 3.8.3-rc1 and later (for the `unittest.mock` package) [0][1].</span>
|
|
<span class="c1"># - Version 4 of the `mock` backport package (https://pypi.org/project/mock/) [2].</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># To work around the problem when running old `mock` versions, we avoid fully stripping out patches from the source</span>
|
|
<span class="c1"># method in favor of replacing them with a "dummy" no-op patch instead.</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># [0] https://docs.python.org/release/3.7.10/whatsnew/changelog.html#python-3-7-8-release-candidate-1</span>
|
|
<span class="c1"># [1] https://docs.python.org/release/3.8.10/whatsnew/changelog.html#python-3-8-3-release-candidate-1</span>
|
|
<span class="c1"># [2] https://mock.readthedocs.io/en/stable/changelog.html#b1</span>
|
|
|
|
<span class="n">PYTHON_DOESNT_HAVE_FIX_FOR_BPO_40126</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="n">sys</span><span class="o">.</span><span class="n">version_info</span><span class="p">[:</span><span class="mi">3</span><span class="p">]</span> <span class="o"><</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">8</span><span class="p">)</span> <span class="ow">or</span> <span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">version_info</span><span class="p">[:</span><span class="mi">2</span><span class="p">]</span> <span class="o">>=</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">8</span><span class="p">)</span> <span class="ow">and</span> <span class="n">sys</span><span class="o">.</span><span class="n">version_info</span><span class="p">[:</span><span class="mi">3</span><span class="p">]</span> <span class="o"><</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">mock</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="nn">_mock_backport</span>
|
|
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
|
|
<span class="n">_mock_backport</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="n">MOCK_BACKPORT_DOESNT_HAVE_FIX_FOR_BPO_40126</span> <span class="o">=</span> <span class="n">_mock_backport</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">_mock_backport</span><span class="o">.</span><span class="n">version_info</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o"><</span> <span class="mi">4</span>
|
|
|
|
<span class="n">AVOID_CLEARING_MOCK_PATCHES</span> <span class="o">=</span> <span class="n">PYTHON_DOESNT_HAVE_FIX_FOR_BPO_40126</span> <span class="ow">or</span> <span class="n">MOCK_BACKPORT_DOESNT_HAVE_FIX_FOR_BPO_40126</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">DummyPatchTarget</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
|
|
<span class="n">dummy_attribute</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="nd">@staticmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">create_dummy_patch</span><span class="p">():</span>
|
|
<span class="k">if</span> <span class="n">mock</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">mock</span><span class="o">.</span><span class="n">patch</span><span class="o">.</span><span class="n">object</span><span class="p">(</span><span class="n">DummyPatchTarget</span><span class="p">(),</span> <span class="s2">"dummy_attribute"</span><span class="p">,</span> <span class="n">new</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ImportError</span><span class="p">(</span><span class="s2">"Missing mock package"</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">delete_patches_if_need</span><span class="p">(</span><span class="n">func</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="s1">'patchings'</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">AVOID_CLEARING_MOCK_PATCHES</span><span class="p">:</span>
|
|
<span class="n">func</span><span class="o">.</span><span class="n">patchings</span><span class="p">[:]</span> <span class="o">=</span> <span class="p">[</span><span class="n">DummyPatchTarget</span><span class="o">.</span><span class="n">create_dummy_patch</span><span class="p">()]</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">func</span><span class="o">.</span><span class="n">patchings</span><span class="p">[:]</span> <span class="o">=</span> <span class="p">[]</span>
|
|
|
|
|
|
<span class="n">_param</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s2">"param"</span><span class="p">,</span> <span class="s2">"args kwargs"</span><span class="p">)</span>
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">param</span><span class="p">(</span><span class="n">_param</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">""" Represents a single parameter to a test case.</span>
|
|
|
|
<span class="sd"> For example::</span>
|
|
|
|
<span class="sd"> >>> p = param("foo", bar=16)</span>
|
|
<span class="sd"> >>> p</span>
|
|
<span class="sd"> param("foo", bar=16)</span>
|
|
<span class="sd"> >>> p.args</span>
|
|
<span class="sd"> ('foo', )</span>
|
|
<span class="sd"> >>> p.kwargs</span>
|
|
<span class="sd"> {'bar': 16}</span>
|
|
|
|
<span class="sd"> Intended to be used as an argument to ``@parameterized``::</span>
|
|
|
|
<span class="sd"> @parameterized([</span>
|
|
<span class="sd"> param("foo", bar=16),</span>
|
|
<span class="sd"> ])</span>
|
|
<span class="sd"> def test_stuff(foo, bar=16):</span>
|
|
<span class="sd"> pass</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__new__</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span> <span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="n">_param</span><span class="o">.</span><span class="fm">__new__</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">)</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">explicit</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">kwargs</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">""" Creates a ``param`` by explicitly specifying ``args`` and</span>
|
|
<span class="sd"> ``kwargs``::</span>
|
|
|
|
<span class="sd"> >>> param.explicit([1,2,3])</span>
|
|
<span class="sd"> param(*(1, 2, 3))</span>
|
|
<span class="sd"> >>> param.explicit(kwargs={"foo": 42})</span>
|
|
<span class="sd"> param(*(), **{"foo": "42"})</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">args</span> <span class="o">=</span> <span class="n">args</span> <span class="ow">or</span> <span class="p">()</span>
|
|
<span class="n">kwargs</span> <span class="o">=</span> <span class="n">kwargs</span> <span class="ow">or</span> <span class="p">{}</span>
|
|
<span class="k">return</span> <span class="bp">cls</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">from_decorator</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">args</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">""" Returns an instance of ``param()`` for ``@parameterized`` argument</span>
|
|
<span class="sd"> ``args``::</span>
|
|
|
|
<span class="sd"> >>> param.from_decorator((42, ))</span>
|
|
<span class="sd"> param(args=(42, ), kwargs={})</span>
|
|
<span class="sd"> >>> param.from_decorator("foo")</span>
|
|
<span class="sd"> param(args=("foo", ), kwargs={})</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">param</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="n">args</span>
|
|
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">))</span> <span class="ow">or</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">Iterable</span><span class="p">):</span>
|
|
<span class="n">args</span> <span class="o">=</span> <span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="p">)</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="bp">cls</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">TypeError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="s2">"after * must be"</span> <span class="ow">not</span> <span class="ow">in</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
|
|
<span class="k">raise</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span>
|
|
<span class="s2">"Parameters must be tuples, but </span><span class="si">%r</span><span class="s2"> is not (hint: use '(</span><span class="si">%r</span><span class="s2">, )')"</span>
|
|
<span class="o">%</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">args</span><span class="p">),</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="s2">"param(*</span><span class="si">%r</span><span class="s2">, **</span><span class="si">%r</span><span class="s2">)"</span> <span class="o">%</span><span class="bp">self</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">QuietOrderedDict</span><span class="p">(</span><span class="n">MaybeOrderedDict</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">""" When OrderedDict is available, use it to make sure that the kwargs in</span>
|
|
<span class="sd"> doc strings are consistently ordered. """</span>
|
|
<span class="fm">__str__</span> <span class="o">=</span> <span class="nb">dict</span><span class="o">.</span><span class="fm">__str__</span>
|
|
<span class="fm">__repr__</span> <span class="o">=</span> <span class="nb">dict</span><span class="o">.</span><span class="fm">__repr__</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">parameterized_argument_value_pairs</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">p</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Return tuples of parameterized arguments and their values.</span>
|
|
|
|
<span class="sd"> This is useful if you are writing your own doc_func</span>
|
|
<span class="sd"> function and need to know the values for each parameter name::</span>
|
|
|
|
<span class="sd"> >>> def func(a, foo=None, bar=42, **kwargs): pass</span>
|
|
<span class="sd"> >>> p = param(1, foo=7, extra=99)</span>
|
|
<span class="sd"> >>> parameterized_argument_value_pairs(func, p)</span>
|
|
<span class="sd"> [("a", 1), ("foo", 7), ("bar", 42), ("**kwargs", {"extra": 99})]</span>
|
|
|
|
<span class="sd"> If the function's first argument is named ``self`` then it will be</span>
|
|
<span class="sd"> ignored::</span>
|
|
|
|
<span class="sd"> >>> def func(self, a): pass</span>
|
|
<span class="sd"> >>> p = param(1)</span>
|
|
<span class="sd"> >>> parameterized_argument_value_pairs(func, p)</span>
|
|
<span class="sd"> [("a", 1)]</span>
|
|
|
|
<span class="sd"> Additionally, empty ``*args`` or ``**kwargs`` will be ignored::</span>
|
|
|
|
<span class="sd"> >>> def func(foo, *args): pass</span>
|
|
<span class="sd"> >>> p = param(1)</span>
|
|
<span class="sd"> >>> parameterized_argument_value_pairs(func, p)</span>
|
|
<span class="sd"> [("foo", 1)]</span>
|
|
<span class="sd"> >>> p = param(1, 16)</span>
|
|
<span class="sd"> >>> parameterized_argument_value_pairs(func, p)</span>
|
|
<span class="sd"> [("foo", 1), ("*args", (16, ))]</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">argspec</span> <span class="o">=</span> <span class="n">getargspec</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
|
|
<span class="n">arg_offset</span> <span class="o">=</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">argspec</span><span class="o">.</span><span class="n">args</span><span class="p">[:</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="p">[</span><span class="s2">"self"</span><span class="p">]</span> <span class="k">else</span> <span class="mi">0</span>
|
|
|
|
<span class="n">named_args</span> <span class="o">=</span> <span class="n">argspec</span><span class="o">.</span><span class="n">args</span><span class="p">[</span><span class="n">arg_offset</span><span class="p">:]</span>
|
|
|
|
<span class="n">result</span> <span class="o">=</span> <span class="n">lzip</span><span class="p">(</span><span class="n">named_args</span><span class="p">,</span> <span class="n">p</span><span class="o">.</span><span class="n">args</span><span class="p">)</span>
|
|
<span class="n">named_args</span> <span class="o">=</span> <span class="n">argspec</span><span class="o">.</span><span class="n">args</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">result</span><span class="p">)</span> <span class="o">+</span> <span class="n">arg_offset</span><span class="p">:]</span>
|
|
<span class="n">varargs</span> <span class="o">=</span> <span class="n">p</span><span class="o">.</span><span class="n">args</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">result</span><span class="p">):]</span>
|
|
|
|
<span class="n">result</span><span class="o">.</span><span class="n">extend</span><span class="p">([</span>
|
|
<span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">p</span><span class="o">.</span><span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">default</span><span class="p">))</span>
|
|
<span class="k">for</span> <span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">default</span><span class="p">)</span>
|
|
<span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">named_args</span><span class="p">,</span> <span class="n">argspec</span><span class="o">.</span><span class="n">defaults</span> <span class="ow">or</span> <span class="p">[])</span>
|
|
<span class="p">])</span>
|
|
|
|
<span class="n">seen_arg_names</span> <span class="o">=</span> <span class="nb">set</span><span class="p">([</span> <span class="n">n</span> <span class="k">for</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">_</span><span class="p">)</span> <span class="ow">in</span> <span class="n">result</span> <span class="p">])</span>
|
|
<span class="n">keywords</span> <span class="o">=</span> <span class="n">QuietOrderedDict</span><span class="p">(</span><span class="nb">sorted</span><span class="p">([</span>
|
|
<span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">p</span><span class="o">.</span><span class="n">kwargs</span><span class="p">[</span><span class="n">name</span><span class="p">])</span>
|
|
<span class="k">for</span> <span class="n">name</span> <span class="ow">in</span> <span class="n">p</span><span class="o">.</span><span class="n">kwargs</span>
|
|
<span class="k">if</span> <span class="n">name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">seen_arg_names</span>
|
|
<span class="p">]))</span>
|
|
|
|
<span class="k">if</span> <span class="n">varargs</span><span class="p">:</span>
|
|
<span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="s2">"*</span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span><span class="p">(</span><span class="n">argspec</span><span class="o">.</span><span class="n">varargs</span><span class="p">,</span> <span class="p">),</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">varargs</span><span class="p">)))</span>
|
|
|
|
<span class="k">if</span> <span class="n">keywords</span><span class="p">:</span>
|
|
<span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="s2">"**</span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span><span class="p">(</span><span class="n">argspec</span><span class="o">.</span><span class="n">keywords</span><span class="p">,</span> <span class="p">),</span> <span class="n">keywords</span><span class="p">))</span>
|
|
|
|
<span class="k">return</span> <span class="n">result</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">short_repr</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">n</span><span class="o">=</span><span class="mi">64</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">""" A shortened repr of ``x`` which is guaranteed to be ``unicode``::</span>
|
|
|
|
<span class="sd"> >>> short_repr("foo")</span>
|
|
<span class="sd"> u"foo"</span>
|
|
<span class="sd"> >>> short_repr("123456789", n=4)</span>
|
|
<span class="sd"> u"12...89"</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="n">x_repr</span> <span class="o">=</span> <span class="n">to_text</span><span class="p">(</span><span class="nb">repr</span><span class="p">(</span><span class="n">x</span><span class="p">))</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">x_repr</span><span class="p">)</span> <span class="o">></span> <span class="n">n</span><span class="p">:</span>
|
|
<span class="n">x_repr</span> <span class="o">=</span> <span class="n">x_repr</span><span class="p">[:</span><span class="n">n</span><span class="o">//</span><span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="s2">"..."</span> <span class="o">+</span> <span class="n">x_repr</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">x_repr</span><span class="p">)</span> <span class="o">-</span> <span class="n">n</span><span class="o">//</span><span class="mi">2</span><span class="p">:]</span>
|
|
<span class="k">return</span> <span class="n">x_repr</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">default_doc_func</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">num</span><span class="p">,</span> <span class="n">p</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">func</span><span class="o">.</span><span class="vm">__doc__</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="kc">None</span>
|
|
|
|
<span class="n">all_args_with_values</span> <span class="o">=</span> <span class="n">parameterized_argument_value_pairs</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Assumes that the function passed is a bound method.</span>
|
|
<span class="n">descs</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"</span><span class="si">%s</span><span class="s2">=</span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">short_repr</span><span class="p">(</span><span class="n">v</span><span class="p">))</span> <span class="k">for</span> <span class="n">n</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">all_args_with_values</span><span class="p">]</span>
|
|
|
|
<span class="c1"># The documentation might be a multiline string, so split it</span>
|
|
<span class="c1"># and just work with the first string, ignoring the period</span>
|
|
<span class="c1"># at the end if there is one.</span>
|
|
<span class="n">first</span><span class="p">,</span> <span class="n">nl</span><span class="p">,</span> <span class="n">rest</span> <span class="o">=</span> <span class="n">func</span><span class="o">.</span><span class="vm">__doc__</span><span class="o">.</span><span class="n">lstrip</span><span class="p">()</span><span class="o">.</span><span class="n">partition</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">)</span>
|
|
<span class="n">suffix</span> <span class="o">=</span> <span class="s2">""</span>
|
|
<span class="k">if</span> <span class="n">first</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s2">"."</span><span class="p">):</span>
|
|
<span class="n">suffix</span> <span class="o">=</span> <span class="s2">"."</span>
|
|
<span class="n">first</span> <span class="o">=</span> <span class="n">first</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
|
|
<span class="n">args</span> <span class="o">=</span> <span class="s2">"</span><span class="si">%s</span><span class="s2">[with </span><span class="si">%s</span><span class="s2">]"</span> <span class="o">%</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">first</span><span class="p">)</span> <span class="ow">and</span> <span class="s2">" "</span> <span class="ow">or</span> <span class="s2">""</span><span class="p">,</span> <span class="s2">", "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">descs</span><span class="p">))</span>
|
|
<span class="k">return</span> <span class="s2">""</span><span class="o">.</span><span class="n">join</span><span class="p">(</span>
|
|
<span class="n">to_text</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
|
|
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="p">[</span><span class="n">first</span><span class="o">.</span><span class="n">rstrip</span><span class="p">(),</span> <span class="n">args</span><span class="p">,</span> <span class="n">suffix</span><span class="p">,</span> <span class="n">nl</span><span class="p">,</span> <span class="n">rest</span><span class="p">]</span>
|
|
<span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">default_name_func</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">num</span><span class="p">,</span> <span class="n">p</span><span class="p">):</span>
|
|
<span class="n">base_name</span> <span class="o">=</span> <span class="n">func</span><span class="o">.</span><span class="vm">__name__</span>
|
|
<span class="n">name_suffix</span> <span class="o">=</span> <span class="s2">"_</span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span><span class="p">(</span><span class="n">num</span><span class="p">,</span> <span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">args</span><span class="p">)</span> <span class="o">></span> <span class="mi">0</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">string_types</span><span class="p">):</span>
|
|
<span class="n">name_suffix</span> <span class="o">+=</span> <span class="s2">"_"</span> <span class="o">+</span> <span class="n">parameterized</span><span class="o">.</span><span class="n">to_safe_name</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
|
|
<span class="k">return</span> <span class="n">base_name</span> <span class="o">+</span> <span class="n">name_suffix</span>
|
|
|
|
|
|
<span class="n">_test_runner_override</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">_test_runner_guess</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="n">_test_runners</span> <span class="o">=</span> <span class="nb">set</span><span class="p">([</span><span class="s2">"unittest"</span><span class="p">,</span> <span class="s2">"unittest2"</span><span class="p">,</span> <span class="s2">"nose"</span><span class="p">,</span> <span class="s2">"nose2"</span><span class="p">,</span> <span class="s2">"pytest"</span><span class="p">])</span>
|
|
<span class="n">_test_runner_aliases</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="s2">"_pytest"</span><span class="p">:</span> <span class="s2">"pytest"</span><span class="p">,</span>
|
|
<span class="p">}</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">set_test_runner</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
|
|
<span class="k">global</span> <span class="n">_test_runner_override</span>
|
|
<span class="k">if</span> <span class="n">name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">_test_runners</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span>
|
|
<span class="s2">"Invalid test runner: </span><span class="si">%r</span><span class="s2"> (must be one of: </span><span class="si">%s</span><span class="s2">)"</span>
|
|
<span class="o">%</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="s2">", "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">_test_runners</span><span class="p">)),</span>
|
|
<span class="p">)</span>
|
|
<span class="n">_test_runner_override</span> <span class="o">=</span> <span class="n">name</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">detect_runner</span><span class="p">():</span>
|
|
<span class="w"> </span><span class="sd">""" Guess which test runner we're using by traversing the stack and looking</span>
|
|
<span class="sd"> for the first matching module. This *should* be reasonably safe, as</span>
|
|
<span class="sd"> it's done during test discovery where the test runner should be the</span>
|
|
<span class="sd"> stack frame immediately outside. """</span>
|
|
<span class="k">if</span> <span class="n">_test_runner_override</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">_test_runner_override</span>
|
|
<span class="k">global</span> <span class="n">_test_runner_guess</span>
|
|
<span class="k">if</span> <span class="n">_test_runner_guess</span> <span class="ow">is</span> <span class="kc">False</span><span class="p">:</span>
|
|
<span class="n">stack</span> <span class="o">=</span> <span class="n">inspect</span><span class="o">.</span><span class="n">stack</span><span class="p">()</span>
|
|
<span class="k">for</span> <span class="n">record</span> <span class="ow">in</span> <span class="nb">reversed</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
|
<span class="n">frame</span> <span class="o">=</span> <span class="n">record</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="n">module</span> <span class="o">=</span> <span class="n">frame</span><span class="o">.</span><span class="n">f_globals</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"__name__"</span><span class="p">)</span><span class="o">.</span><span class="n">partition</span><span class="p">(</span><span class="s2">"."</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="n">module</span> <span class="ow">in</span> <span class="n">_test_runner_aliases</span><span class="p">:</span>
|
|
<span class="n">module</span> <span class="o">=</span> <span class="n">_test_runner_aliases</span><span class="p">[</span><span class="n">module</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="n">module</span> <span class="ow">in</span> <span class="n">_test_runners</span><span class="p">:</span>
|
|
<span class="n">_test_runner_guess</span> <span class="o">=</span> <span class="n">module</span>
|
|
<span class="k">break</span>
|
|
<span class="k">if</span> <span class="n">record</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s2">"python2.6/unittest.py"</span><span class="p">):</span>
|
|
<span class="n">_test_runner_guess</span> <span class="o">=</span> <span class="s2">"unittest"</span>
|
|
<span class="k">break</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">_test_runner_guess</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="k">return</span> <span class="n">_test_runner_guess</span>
|
|
|
|
|
|
|
|
<div class="viewcode-block" id="parameterized">
|
|
<a class="viewcode-back" href="../../api/evennia.utils.verb_conjugation.tests.html#evennia.commands.default.tests.parameterized">[docs]</a>
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">parameterized</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">""" Parameterize a test case::</span>
|
|
|
|
<span class="sd"> class TestInt(object):</span>
|
|
<span class="sd"> @parameterized([</span>
|
|
<span class="sd"> ("A", 10),</span>
|
|
<span class="sd"> ("F", 15),</span>
|
|
<span class="sd"> param("10", 42, base=42)</span>
|
|
<span class="sd"> ])</span>
|
|
<span class="sd"> def test_int(self, input, expected, base=16):</span>
|
|
<span class="sd"> actual = int(input, base=base)</span>
|
|
<span class="sd"> assert_equal(actual, expected)</span>
|
|
|
|
<span class="sd"> @parameterized([</span>
|
|
<span class="sd"> (2, 3, 5)</span>
|
|
<span class="sd"> (3, 5, 8),</span>
|
|
<span class="sd"> ])</span>
|
|
<span class="sd"> def test_add(a, b, expected):</span>
|
|
<span class="sd"> assert_equal(a + b, expected)</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<div class="viewcode-block" id="parameterized.__init__">
|
|
<a class="viewcode-back" href="../../api/evennia.utils.verb_conjugation.tests.html#evennia.commands.default.tests.parameterized.__init__">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">input</span><span class="p">,</span> <span class="n">doc_func</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">skip_on_empty</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">get_input</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">input_as_callable</span><span class="p">(</span><span class="nb">input</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">doc_func</span> <span class="o">=</span> <span class="n">doc_func</span> <span class="ow">or</span> <span class="n">default_doc_func</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">skip_on_empty</span> <span class="o">=</span> <span class="n">skip_on_empty</span></div>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">test_func</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">assert_not_in_testcase_subclass</span><span class="p">()</span>
|
|
|
|
<span class="nd">@wraps</span><span class="p">(</span><span class="n">test_func</span><span class="p">)</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">wrapper</span><span class="p">(</span><span class="n">test_self</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="n">test_cls</span> <span class="o">=</span> <span class="n">test_self</span> <span class="ow">and</span> <span class="nb">type</span><span class="p">(</span><span class="n">test_self</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">test_self</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="nb">issubclass</span><span class="p">(</span><span class="n">test_cls</span><span class="p">,</span> <span class="n">InstanceType</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">((</span>
|
|
<span class="s2">"@parameterized can't be used with old-style classes, but "</span>
|
|
<span class="s2">"</span><span class="si">%r</span><span class="s2"> has an old-style class. Consider using a new-style "</span>
|
|
<span class="s2">"class, or '@parameterized.expand' "</span>
|
|
<span class="s2">"(see http://stackoverflow.com/q/54867/71522 for more "</span>
|
|
<span class="s2">"information on old-style classes)."</span>
|
|
<span class="p">)</span> <span class="o">%</span><span class="p">(</span><span class="n">test_self</span><span class="p">,</span> <span class="p">))</span>
|
|
|
|
<span class="n">original_doc</span> <span class="o">=</span> <span class="n">wrapper</span><span class="o">.</span><span class="vm">__doc__</span>
|
|
<span class="k">for</span> <span class="n">num</span><span class="p">,</span> <span class="n">args</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">wrapper</span><span class="o">.</span><span class="n">parameterized_input</span><span class="p">):</span>
|
|
<span class="n">p</span> <span class="o">=</span> <span class="n">param</span><span class="o">.</span><span class="n">from_decorator</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
|
|
<span class="n">unbound_func</span><span class="p">,</span> <span class="n">nose_tuple</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">param_as_nose_tuple</span><span class="p">(</span><span class="n">test_self</span><span class="p">,</span> <span class="n">test_func</span><span class="p">,</span> <span class="n">num</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">wrapper</span><span class="o">.</span><span class="vm">__doc__</span> <span class="o">=</span> <span class="n">nose_tuple</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="vm">__doc__</span>
|
|
<span class="c1"># Nose uses `getattr(instance, test_func.__name__)` to get</span>
|
|
<span class="c1"># a method bound to the test instance (as opposed to a</span>
|
|
<span class="c1"># method bound to the instance of the class created when</span>
|
|
<span class="c1"># tests were being enumerated). Set a value here to make</span>
|
|
<span class="c1"># sure nose can get the correct test method.</span>
|
|
<span class="k">if</span> <span class="n">test_self</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="nb">setattr</span><span class="p">(</span><span class="n">test_cls</span><span class="p">,</span> <span class="n">test_func</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="n">unbound_func</span><span class="p">)</span>
|
|
<span class="k">yield</span> <span class="n">nose_tuple</span>
|
|
<span class="k">finally</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">test_self</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="nb">delattr</span><span class="p">(</span><span class="n">test_cls</span><span class="p">,</span> <span class="n">test_func</span><span class="o">.</span><span class="vm">__name__</span><span class="p">)</span>
|
|
<span class="n">wrapper</span><span class="o">.</span><span class="vm">__doc__</span> <span class="o">=</span> <span class="n">original_doc</span>
|
|
|
|
<span class="nb">input</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_input</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">input</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">skip_on_empty</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
|
|
<span class="s2">"Parameters iterable is empty (hint: use "</span>
|
|
<span class="s2">"`parameterized([], skip_on_empty=True)` to skip "</span>
|
|
<span class="s2">"this test when the input is empty)"</span>
|
|
<span class="p">)</span>
|
|
<span class="n">wrapper</span> <span class="o">=</span> <span class="n">wraps</span><span class="p">(</span><span class="n">test_func</span><span class="p">)(</span><span class="n">skip_on_empty_helper</span><span class="p">)</span>
|
|
|
|
<span class="n">wrapper</span><span class="o">.</span><span class="n">parameterized_input</span> <span class="o">=</span> <span class="nb">input</span>
|
|
<span class="n">wrapper</span><span class="o">.</span><span class="n">parameterized_func</span> <span class="o">=</span> <span class="n">test_func</span>
|
|
<span class="n">test_func</span><span class="o">.</span><span class="vm">__name__</span> <span class="o">=</span> <span class="s2">"_parameterized_original_</span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span><span class="p">(</span><span class="n">test_func</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="p">)</span>
|
|
|
|
<span class="k">return</span> <span class="n">wrapper</span>
|
|
|
|
<div class="viewcode-block" id="parameterized.param_as_nose_tuple">
|
|
<a class="viewcode-back" href="../../api/evennia.utils.verb_conjugation.tests.html#evennia.commands.default.tests.parameterized.param_as_nose_tuple">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">param_as_nose_tuple</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">test_self</span><span class="p">,</span> <span class="n">func</span><span class="p">,</span> <span class="n">num</span><span class="p">,</span> <span class="n">p</span><span class="p">):</span>
|
|
<span class="n">nose_func</span> <span class="o">=</span> <span class="n">wraps</span><span class="p">(</span><span class="n">func</span><span class="p">)(</span><span class="k">lambda</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">func</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="o">**</span><span class="n">args</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]))</span>
|
|
<span class="n">nose_func</span><span class="o">.</span><span class="vm">__doc__</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">doc_func</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">num</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
|
|
<span class="c1"># Track the unbound function because we need to setattr the unbound</span>
|
|
<span class="c1"># function onto the class for nose to work (see comments above), and</span>
|
|
<span class="c1"># Python 3 doesn't let us pull the function out of a bound method.</span>
|
|
<span class="n">unbound_func</span> <span class="o">=</span> <span class="n">nose_func</span>
|
|
<span class="k">if</span> <span class="n">test_self</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="c1"># Under nose on Py2 we need to return an unbound method to make</span>
|
|
<span class="c1"># sure that the `self` in the method is properly shared with the</span>
|
|
<span class="c1"># `self` used in `setUp` and `tearDown`. But only there. Everyone</span>
|
|
<span class="c1"># else needs a bound method.</span>
|
|
<span class="n">func_self</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="kc">None</span> <span class="k">if</span> <span class="n">PY2</span> <span class="ow">and</span> <span class="n">detect_runner</span><span class="p">()</span> <span class="o">==</span> <span class="s2">"nose"</span> <span class="k">else</span>
|
|
<span class="n">test_self</span>
|
|
<span class="p">)</span>
|
|
<span class="n">nose_func</span> <span class="o">=</span> <span class="n">make_method</span><span class="p">(</span><span class="n">nose_func</span><span class="p">,</span> <span class="n">func_self</span><span class="p">,</span> <span class="nb">type</span><span class="p">(</span><span class="n">test_self</span><span class="p">))</span>
|
|
<span class="k">return</span> <span class="n">unbound_func</span><span class="p">,</span> <span class="p">(</span><span class="n">nose_func</span><span class="p">,</span> <span class="p">)</span> <span class="o">+</span> <span class="n">p</span><span class="o">.</span><span class="n">args</span> <span class="o">+</span> <span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">kwargs</span> <span class="ow">or</span> <span class="p">{},</span> <span class="p">)</span></div>
|
|
|
|
|
|
<div class="viewcode-block" id="parameterized.assert_not_in_testcase_subclass">
|
|
<a class="viewcode-back" href="../../api/evennia.utils.verb_conjugation.tests.html#evennia.commands.default.tests.parameterized.assert_not_in_testcase_subclass">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">assert_not_in_testcase_subclass</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="n">parent_classes</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_terrible_magic_get_defining_classes</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="nb">any</span><span class="p">(</span><span class="nb">issubclass</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">TestCase</span><span class="p">)</span> <span class="k">for</span> <span class="bp">cls</span> <span class="ow">in</span> <span class="n">parent_classes</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s2">"Warning: '@parameterized' tests won't work "</span>
|
|
<span class="s2">"inside subclasses of 'TestCase' - use "</span>
|
|
<span class="s2">"'@parameterized.expand' instead."</span><span class="p">)</span></div>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_terrible_magic_get_defining_classes</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">""" Returns the set of parent classes of the class currently being defined.</span>
|
|
<span class="sd"> Will likely only work if called from the ``parameterized`` decorator.</span>
|
|
<span class="sd"> This function is entirely @brandon_rhodes's fault, as he suggested</span>
|
|
<span class="sd"> the implementation: http://stackoverflow.com/a/8793684/71522</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">stack</span> <span class="o">=</span> <span class="n">inspect</span><span class="o">.</span><span class="n">stack</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">stack</span><span class="p">)</span> <span class="o"><=</span> <span class="mi">4</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="p">[]</span>
|
|
<span class="n">frame</span> <span class="o">=</span> <span class="n">stack</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span>
|
|
<span class="n">code_context</span> <span class="o">=</span> <span class="n">frame</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="ow">and</span> <span class="n">frame</span><span class="p">[</span><span class="mi">4</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="p">(</span><span class="n">code_context</span> <span class="ow">and</span> <span class="n">code_context</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"class "</span><span class="p">)):</span>
|
|
<span class="k">return</span> <span class="p">[]</span>
|
|
<span class="n">_</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">parents</span> <span class="o">=</span> <span class="n">code_context</span><span class="o">.</span><span class="n">partition</span><span class="p">(</span><span class="s2">"("</span><span class="p">)</span>
|
|
<span class="n">parents</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="n">parents</span><span class="o">.</span><span class="n">partition</span><span class="p">(</span><span class="s2">")"</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="nb">eval</span><span class="p">(</span><span class="s2">"["</span> <span class="o">+</span> <span class="n">parents</span> <span class="o">+</span> <span class="s2">"]"</span><span class="p">,</span> <span class="n">frame</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">f_globals</span><span class="p">,</span> <span class="n">frame</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">f_locals</span><span class="p">)</span>
|
|
|
|
<div class="viewcode-block" id="parameterized.input_as_callable">
|
|
<a class="viewcode-back" href="../../api/evennia.utils.verb_conjugation.tests.html#evennia.commands.default.tests.parameterized.input_as_callable">[docs]</a>
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">input_as_callable</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="nb">input</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="nb">callable</span><span class="p">(</span><span class="nb">input</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="k">lambda</span><span class="p">:</span> <span class="bp">cls</span><span class="o">.</span><span class="n">check_input_values</span><span class="p">(</span><span class="nb">input</span><span class="p">())</span>
|
|
<span class="n">input_values</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="n">check_input_values</span><span class="p">(</span><span class="nb">input</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">input_values</span></div>
|
|
|
|
|
|
<div class="viewcode-block" id="parameterized.check_input_values">
|
|
<a class="viewcode-back" href="../../api/evennia.utils.verb_conjugation.tests.html#evennia.commands.default.tests.parameterized.check_input_values">[docs]</a>
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">check_input_values</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">input_values</span><span class="p">):</span>
|
|
<span class="c1"># Explicitly convery non-list inputs to a list so that:</span>
|
|
<span class="c1"># 1. A helpful exception will be raised if they aren't iterable, and</span>
|
|
<span class="c1"># 2. Generators are unwrapped exactly once (otherwise `nosetests</span>
|
|
<span class="c1"># --processes=n` has issues; see:</span>
|
|
<span class="c1"># https://github.com/wolever/nose-parameterized/pull/31)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">input_values</span><span class="p">,</span> <span class="nb">list</span><span class="p">):</span>
|
|
<span class="n">input_values</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">input_values</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="p">[</span> <span class="n">param</span><span class="o">.</span><span class="n">from_decorator</span><span class="p">(</span><span class="n">p</span><span class="p">)</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">input_values</span> <span class="p">]</span></div>
|
|
|
|
|
|
<div class="viewcode-block" id="parameterized.expand">
|
|
<a class="viewcode-back" href="../../api/evennia.utils.verb_conjugation.tests.html#evennia.commands.default.tests.parameterized.expand">[docs]</a>
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">expand</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="nb">input</span><span class="p">,</span> <span class="n">name_func</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">doc_func</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">skip_on_empty</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
|
|
<span class="n">namespace</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">**</span><span class="n">legacy</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">""" A "brute force" method of parameterizing test cases. Creates new</span>
|
|
<span class="sd"> test cases and injects them into the namespace that the wrapped</span>
|
|
<span class="sd"> function is being defined in. Useful for parameterizing tests in</span>
|
|
<span class="sd"> subclasses of 'UnitTest', where Nose test generators don't work.</span>
|
|
|
|
<span class="sd"> :param input: An iterable of values to pass to the test function.</span>
|
|
<span class="sd"> :param name_func: A function that takes a single argument (the</span>
|
|
<span class="sd"> value from the input iterable) and returns a string to use as</span>
|
|
<span class="sd"> the name of the test case. If not provided, the name of the</span>
|
|
<span class="sd"> test case will be the name of the test function with the</span>
|
|
<span class="sd"> parameter value appended.</span>
|
|
<span class="sd"> :param doc_func: A function that takes a single argument (the</span>
|
|
<span class="sd"> value from the input iterable) and returns a string to use as</span>
|
|
<span class="sd"> the docstring of the test case. If not provided, the docstring</span>
|
|
<span class="sd"> of the test case will be the docstring of the test function.</span>
|
|
<span class="sd"> :param skip_on_empty: If True, the test will be skipped if the</span>
|
|
<span class="sd"> input iterable is empty. If False, a ValueError will be raised</span>
|
|
<span class="sd"> if the input iterable is empty.</span>
|
|
<span class="sd"> :param namespace: The namespace (dict-like) to inject the test cases</span>
|
|
<span class="sd"> into. If not provided, the namespace of the test function will</span>
|
|
<span class="sd"> be used.</span>
|
|
|
|
<span class="sd"> >>> @parameterized.expand([("foo", 1, 2)])</span>
|
|
<span class="sd"> ... def test_add1(name, input, expected):</span>
|
|
<span class="sd"> ... actual = add1(input)</span>
|
|
<span class="sd"> ... assert_equal(actual, expected)</span>
|
|
<span class="sd"> ...</span>
|
|
<span class="sd"> >>> locals()</span>
|
|
<span class="sd"> ... 'test_add1_foo_0': <function ...> ...</span>
|
|
<span class="sd"> >>></span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="k">if</span> <span class="s2">"testcase_func_name"</span> <span class="ow">in</span> <span class="n">legacy</span><span class="p">:</span>
|
|
<span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s2">"testcase_func_name= is deprecated; use name_func="</span><span class="p">,</span>
|
|
<span class="ne">DeprecationWarning</span><span class="p">,</span> <span class="n">stacklevel</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">name_func</span><span class="p">:</span>
|
|
<span class="n">name_func</span> <span class="o">=</span> <span class="n">legacy</span><span class="p">[</span><span class="s2">"testcase_func_name"</span><span class="p">]</span>
|
|
|
|
<span class="k">if</span> <span class="s2">"testcase_func_doc"</span> <span class="ow">in</span> <span class="n">legacy</span><span class="p">:</span>
|
|
<span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s2">"testcase_func_doc= is deprecated; use doc_func="</span><span class="p">,</span>
|
|
<span class="ne">DeprecationWarning</span><span class="p">,</span> <span class="n">stacklevel</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">doc_func</span><span class="p">:</span>
|
|
<span class="n">doc_func</span> <span class="o">=</span> <span class="n">legacy</span><span class="p">[</span><span class="s2">"testcase_func_doc"</span><span class="p">]</span>
|
|
|
|
<span class="n">doc_func</span> <span class="o">=</span> <span class="n">doc_func</span> <span class="ow">or</span> <span class="n">default_doc_func</span>
|
|
<span class="n">name_func</span> <span class="o">=</span> <span class="n">name_func</span> <span class="ow">or</span> <span class="n">default_name_func</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">parameterized_expand_wrapper</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">instance</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="n">frame_locals</span> <span class="o">=</span> <span class="n">namespace</span>
|
|
<span class="k">if</span> <span class="n">frame_locals</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">frame_locals</span> <span class="o">=</span> <span class="n">inspect</span><span class="o">.</span><span class="n">currentframe</span><span class="p">()</span><span class="o">.</span><span class="n">f_back</span><span class="o">.</span><span class="n">f_locals</span>
|
|
|
|
<span class="n">parameters</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="n">input_as_callable</span><span class="p">(</span><span class="nb">input</span><span class="p">)()</span>
|
|
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">parameters</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">skip_on_empty</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
|
|
<span class="s2">"Parameters iterable is empty (hint: use "</span>
|
|
<span class="s2">"`parameterized.expand([], skip_on_empty=True)` to skip "</span>
|
|
<span class="s2">"this test when the input is empty)"</span>
|
|
<span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">wraps</span><span class="p">(</span><span class="n">f</span><span class="p">)(</span><span class="n">skip_on_empty_helper</span><span class="p">)</span>
|
|
|
|
<span class="n">digits</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">parameters</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">))</span>
|
|
<span class="k">for</span> <span class="n">num</span><span class="p">,</span> <span class="n">p</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">parameters</span><span class="p">):</span>
|
|
<span class="n">name</span> <span class="o">=</span> <span class="n">name_func</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="s2">"{num:0></span><span class="si">{digits}</span><span class="s2">}"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">digits</span><span class="o">=</span><span class="n">digits</span><span class="p">,</span> <span class="n">num</span><span class="o">=</span><span class="n">num</span><span class="p">),</span> <span class="n">p</span><span class="p">)</span>
|
|
<span class="c1"># If the original function has patches applied by 'mock.patch',</span>
|
|
<span class="c1"># re-construct all patches on the just former decoration layer</span>
|
|
<span class="c1"># of param_as_standalone_func so as not to share</span>
|
|
<span class="c1"># patch objects between new functions</span>
|
|
<span class="n">nf</span> <span class="o">=</span> <span class="n">reapply_patches_if_need</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
|
|
<span class="n">frame_locals</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="n">param_as_standalone_func</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">nf</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
|
|
<span class="n">frame_locals</span><span class="p">[</span><span class="n">name</span><span class="p">]</span><span class="o">.</span><span class="vm">__doc__</span> <span class="o">=</span> <span class="n">doc_func</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">num</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Delete original patches to prevent new function from evaluating</span>
|
|
<span class="c1"># original patching object as well as re-constructed patches.</span>
|
|
<span class="n">delete_patches_if_need</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
|
|
|
|
<span class="n">f</span><span class="o">.</span><span class="n">__test__</span> <span class="o">=</span> <span class="kc">False</span>
|
|
|
|
<span class="k">return</span> <span class="n">parameterized_expand_wrapper</span></div>
|
|
|
|
|
|
<div class="viewcode-block" id="parameterized.param_as_standalone_func">
|
|
<a class="viewcode-back" href="../../api/evennia.utils.verb_conjugation.tests.html#evennia.commands.default.tests.parameterized.param_as_standalone_func">[docs]</a>
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">param_as_standalone_func</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">func</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">inspect</span><span class="o">.</span><span class="n">iscoroutinefunction</span><span class="p">(</span><span class="n">func</span><span class="p">):</span>
|
|
<span class="nd">@wraps</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
|
|
<span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">standalone_func</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="k">await</span> <span class="n">func</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">a</span> <span class="o">+</span> <span class="n">p</span><span class="o">.</span><span class="n">args</span><span class="p">),</span> <span class="o">**</span><span class="n">p</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="nd">@wraps</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">standalone_func</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="n">func</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">a</span> <span class="o">+</span> <span class="n">p</span><span class="o">.</span><span class="n">args</span><span class="p">),</span> <span class="o">**</span><span class="n">p</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">)</span>
|
|
|
|
<span class="n">standalone_func</span><span class="o">.</span><span class="vm">__name__</span> <span class="o">=</span> <span class="n">name</span>
|
|
|
|
<span class="c1"># place_as is used by py.test to determine what source file should be</span>
|
|
<span class="c1"># used for this test.</span>
|
|
<span class="n">standalone_func</span><span class="o">.</span><span class="n">place_as</span> <span class="o">=</span> <span class="n">func</span>
|
|
|
|
<span class="c1"># Remove __wrapped__ because py.test will try to look at __wrapped__</span>
|
|
<span class="c1"># to determine which parameters should be used with this test case,</span>
|
|
<span class="c1"># and obviously we don't need it to do any parameterization.</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">del</span> <span class="n">standalone_func</span><span class="o">.</span><span class="n">__wrapped__</span>
|
|
<span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
|
|
<span class="k">pass</span>
|
|
<span class="k">return</span> <span class="n">standalone_func</span></div>
|
|
|
|
|
|
<div class="viewcode-block" id="parameterized.to_safe_name">
|
|
<a class="viewcode-back" href="../../api/evennia.utils.verb_conjugation.tests.html#evennia.commands.default.tests.parameterized.to_safe_name">[docs]</a>
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">to_safe_name</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">s</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
|
|
<span class="n">s</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="s2">"[^a-zA-Z0-9_]+"</span><span class="p">,</span> <span class="s2">"_"</span><span class="p">,</span> <span class="n">s</span><span class="p">))</span></div>
|
|
</div>
|
|
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">parameterized_class</span><span class="p">(</span><span class="n">attrs</span><span class="p">,</span> <span class="n">input_values</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">class_name_func</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">classname_func</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">""" Parameterizes a test class by setting attributes on the class.</span>
|
|
|
|
<span class="sd"> Can be used in two ways:</span>
|
|
|
|
<span class="sd"> 1) With a list of dictionaries containing attributes to override::</span>
|
|
|
|
<span class="sd"> @parameterized_class([</span>
|
|
<span class="sd"> { "username": "foo" },</span>
|
|
<span class="sd"> { "username": "bar", "access_level": 2 },</span>
|
|
<span class="sd"> ])</span>
|
|
<span class="sd"> class TestUserAccessLevel(TestCase):</span>
|
|
<span class="sd"> ...</span>
|
|
|
|
<span class="sd"> 2) With a tuple of attributes, then a list of tuples of values:</span>
|
|
|
|
<span class="sd"> @parameterized_class(("username", "access_level"), [</span>
|
|
<span class="sd"> ("foo", 1),</span>
|
|
<span class="sd"> ("bar", 2)</span>
|
|
<span class="sd"> ])</span>
|
|
<span class="sd"> class TestUserAccessLevel(TestCase):</span>
|
|
<span class="sd"> ...</span>
|
|
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">attrs</span><span class="p">,</span> <span class="n">string_types</span><span class="p">):</span>
|
|
<span class="n">attrs</span> <span class="o">=</span> <span class="p">[</span><span class="n">attrs</span><span class="p">]</span>
|
|
|
|
<span class="n">input_dicts</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="n">attrs</span> <span class="k">if</span> <span class="n">input_values</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span>
|
|
<span class="p">[</span><span class="nb">dict</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">attrs</span><span class="p">,</span> <span class="n">vals</span><span class="p">))</span> <span class="k">for</span> <span class="n">vals</span> <span class="ow">in</span> <span class="n">input_values</span><span class="p">]</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="n">class_name_func</span> <span class="o">=</span> <span class="n">class_name_func</span> <span class="ow">or</span> <span class="n">default_class_name_func</span>
|
|
|
|
<span class="k">if</span> <span class="n">classname_func</span><span class="p">:</span>
|
|
<span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span>
|
|
<span class="s2">"classname_func= is deprecated; use class_name_func= instead. "</span>
|
|
<span class="s2">"See: https://github.com/wolever/parameterized/pull/74#issuecomment-613577057"</span><span class="p">,</span>
|
|
<span class="ne">DeprecationWarning</span><span class="p">,</span>
|
|
<span class="n">stacklevel</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="n">class_name_func</span> <span class="o">=</span> <span class="k">lambda</span> <span class="bp">cls</span><span class="p">,</span> <span class="n">idx</span><span class="p">,</span> <span class="nb">input</span><span class="p">:</span> <span class="n">classname_func</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">idx</span><span class="p">,</span> <span class="n">input_dicts</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">decorator</span><span class="p">(</span><span class="n">base_class</span><span class="p">):</span>
|
|
<span class="n">test_class_module</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="p">[</span><span class="n">base_class</span><span class="o">.</span><span class="vm">__module__</span><span class="p">]</span><span class="o">.</span><span class="vm">__dict__</span>
|
|
<span class="k">for</span> <span class="n">idx</span><span class="p">,</span> <span class="n">input_dict</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">input_dicts</span><span class="p">):</span>
|
|
<span class="n">test_class_dict</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">base_class</span><span class="o">.</span><span class="vm">__dict__</span><span class="p">)</span>
|
|
<span class="n">test_class_dict</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">input_dict</span><span class="p">)</span>
|
|
|
|
<span class="n">name</span> <span class="o">=</span> <span class="n">class_name_func</span><span class="p">(</span><span class="n">base_class</span><span class="p">,</span> <span class="n">idx</span><span class="p">,</span> <span class="n">input_dict</span><span class="p">)</span>
|
|
|
|
<span class="n">test_class_module</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="nb">type</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="p">(</span><span class="n">base_class</span><span class="p">,</span> <span class="p">),</span> <span class="n">test_class_dict</span><span class="p">)</span>
|
|
|
|
<span class="c1"># We need to leave the base class in place (see issue #73), but if we</span>
|
|
<span class="c1"># leave the test_ methods in place, the test runner will try to pick</span>
|
|
<span class="c1"># them up and run them... which doesn't make sense, since no parameters</span>
|
|
<span class="c1"># will have been applied.</span>
|
|
<span class="c1"># Address this by iterating over the base class and remove all test</span>
|
|
<span class="c1"># methods.</span>
|
|
<span class="k">for</span> <span class="n">method_name</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">base_class</span><span class="o">.</span><span class="vm">__dict__</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">method_name</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"test"</span><span class="p">):</span>
|
|
<span class="nb">delattr</span><span class="p">(</span><span class="n">base_class</span><span class="p">,</span> <span class="n">method_name</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">base_class</span>
|
|
|
|
<span class="k">return</span> <span class="n">decorator</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">get_class_name_suffix</span><span class="p">(</span><span class="n">params_dict</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="s2">"name"</span> <span class="ow">in</span> <span class="n">params_dict</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">parameterized</span><span class="o">.</span><span class="n">to_safe_name</span><span class="p">(</span><span class="n">params_dict</span><span class="p">[</span><span class="s2">"name"</span><span class="p">])</span>
|
|
|
|
<span class="n">params_vals</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="n">params_dict</span><span class="o">.</span><span class="n">values</span><span class="p">()</span> <span class="k">if</span> <span class="n">PY3</span> <span class="k">else</span>
|
|
<span class="p">(</span><span class="n">v</span> <span class="k">for</span> <span class="p">(</span><span class="n">_</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">params_dict</span><span class="o">.</span><span class="n">items</span><span class="p">()))</span>
|
|
<span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">parameterized</span><span class="o">.</span><span class="n">to_safe_name</span><span class="p">(</span><span class="nb">next</span><span class="p">((</span>
|
|
<span class="n">v</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">params_vals</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="n">string_types</span><span class="p">)</span>
|
|
<span class="p">),</span> <span class="s2">""</span><span class="p">))</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">default_class_name_func</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">num</span><span class="p">,</span> <span class="n">params_dict</span><span class="p">):</span>
|
|
<span class="n">suffix</span> <span class="o">=</span> <span class="n">get_class_name_suffix</span><span class="p">(</span><span class="n">params_dict</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="s2">"</span><span class="si">%s</span><span class="s2">_</span><span class="si">%s%s</span><span class="s2">"</span> <span class="o">%</span><span class="p">(</span>
|
|
<span class="bp">cls</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span>
|
|
<span class="n">num</span><span class="p">,</span>
|
|
<span class="n">suffix</span> <span class="ow">and</span> <span class="s2">"_"</span> <span class="o">+</span> <span class="n">suffix</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
</pre></div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<div class="related" role="navigation" aria-label="related navigation">
|
|
<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="nav-item nav-item-0"><a href="../../index.html">Evennia latest</a> »</li>
|
|
<li class="nav-item nav-item-1"><a href="../index.html" >Module code</a> »</li>
|
|
<li class="nav-item nav-item-this"><a href="">parameterized.parameterized</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
|
|
|
|
<div class="footer" role="contentinfo">
|
|
© Copyright 2024, The Evennia developer community.
|
|
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.2.3.
|
|
</div>
|
|
</body>
|
|
</html> |