Skip to content

Commit

Permalink
Update README, docs build
Browse files Browse the repository at this point in the history
  • Loading branch information
eriknyquist committed Oct 3, 2022
1 parent cb43b73 commit 497d9ef
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 23 deletions.
24 changes: 24 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,30 @@ conditions must be true:
* Both objects are instances of the same class
* Both objects contain matching attribute names and values

Object instance hashing
-----------------------

Objects can be uniquely hashed based on their instance attribute values, using the builtin
``hash()`` function. This means, for example, that you can use object instances as dict keys:

.. code:: python
from versionedobj import VersionedObject
class Person(VersionedObject):
name = "sam"
age = 31
p1 = Person()
p2 = Person()
# Change 1 value on p2 so the hash value is different
p2.age = 32
d = {p1: "a", p2: "b"}
print(d)
# { Person({"name": "sam", "age": 31}): "a", Person({"name": "sam", "age": 32}): "b" }
Performance/stress test visualization
-------------------------------------

Expand Down
21 changes: 19 additions & 2 deletions docs/_modules/versionedobj/object.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,12 @@
<div itemprop="articleBody">

<h1>Source code for versionedobj.object</h1><div class="highlight"><pre>
<span></span><span class="kn">import</span> <span class="nn">sys</span>
<span></span><span class="kn">import</span> <span class="nn">json</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">inspect</span>

<span class="kn">from</span> <span class="nn">versionedobj.exceptions</span> <span class="kn">import</span> <span class="n">InvalidVersionAttributeError</span><span class="p">,</span> <span class="n">InputValidationError</span>
<span class="kn">from</span> <span class="nn">versionedobj.utils</span> <span class="kn">import</span> <span class="n">_ObjField</span><span class="p">,</span> <span class="n">_iter_obj_attrs</span><span class="p">,</span> <span class="n">_walk_obj_attrs</span>
<span class="kn">from</span> <span class="nn">versionedobj.utils</span> <span class="kn">import</span> <span class="n">_ObjField</span><span class="p">,</span> <span class="n">_iter_obj_attrs</span><span class="p">,</span> <span class="n">_walk_obj_attrs</span><span class="p">,</span> <span class="n">_obj_to_dict</span>


<div class="viewcode-block" id="migration"><a class="viewcode-back" href="../../versionedobj.html#versionedobj.object.migration">[docs]</a><span class="k">def</span> <span class="nf">migration</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">from_version</span><span class="p">,</span> <span class="n">to_version</span><span class="p">):</span>
Expand Down Expand Up @@ -166,6 +167,16 @@ <h1>Source code for versionedobj.object</h1><div class="highlight"><pre>
<span class="n">field</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">initial_values</span><span class="p">[</span><span class="n">dotname</span><span class="p">]</span>
<span class="n">field</span><span class="o">.</span><span class="n">set_obj_field</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span></div>

<span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">json_str</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">_obj_to_dict</span><span class="p">(</span><span class="bp">self</span><span class="p">))</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">json_str</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">36</span><span class="p">:</span>
<span class="n">json_str</span> <span class="o">=</span> <span class="n">json_str</span><span class="p">[:</span><span class="mi">30</span><span class="p">]</span> <span class="o">+</span> <span class="s1">&#39; ... }&#39;</span>

<span class="k">return</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="si">}</span><span class="s2">(</span><span class="si">{</span><span class="n">json_str</span><span class="si">}</span><span class="s2">)&quot;</span>

<span class="k">def</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="bp">self</span><span class="o">.</span><span class="fm">__str__</span><span class="p">()</span>

<span class="k">def</span> <span class="fm">__eq__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span> <span class="o">!=</span> <span class="n">other</span><span class="o">.</span><span class="vm">__class__</span><span class="p">:</span>
<span class="k">return</span> <span class="kc">False</span>
Expand All @@ -192,6 +203,12 @@ <h1>Source code for versionedobj.object</h1><div class="highlight"><pre>

<span class="k">return</span> <span class="kc">True</span>

<span class="k">def</span> <span class="nf">__neq__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="fm">__eq__</span><span class="p">()</span>

<span class="k">def</span> <span class="fm">__hash__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">hash</span><span class="p">(</span><span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">_obj_to_dict</span><span class="p">(</span><span class="bp">self</span><span class="p">)))</span>

<span class="k">def</span> <span class="nf">_vobj__populate_instance</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">_iter_obj_attrs</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">):</span>
<span class="n">val</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
Expand Down
14 changes: 2 additions & 12 deletions docs/_modules/versionedobj/serializer.html
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ <h1>Source code for versionedobj.serializer</h1><div class="highlight"><pre>
<span class="kn">from</span> <span class="nn">json.decoder</span> <span class="kn">import</span> <span class="n">JSONDecodeError</span>

<span class="kn">from</span> <span class="nn">versionedobj.object</span> <span class="kn">import</span> <span class="n">VersionedObject</span><span class="p">,</span> <span class="n">CustomValue</span>
<span class="kn">from</span> <span class="nn">versionedobj.utils</span> <span class="kn">import</span> <span class="n">_ObjField</span><span class="p">,</span> <span class="n">_walk_obj_attrs</span><span class="p">,</span> <span class="n">_field_should_be_skipped</span>
<span class="kn">from</span> <span class="nn">versionedobj.utils</span> <span class="kn">import</span> <span class="n">_ObjField</span><span class="p">,</span> <span class="n">_walk_obj_attrs</span><span class="p">,</span> <span class="n">_field_should_be_skipped</span><span class="p">,</span> <span class="n">_obj_to_dict</span>
<span class="kn">from</span> <span class="nn">versionedobj.exceptions</span> <span class="kn">import</span> <span class="n">InvalidFilterError</span><span class="p">,</span> <span class="n">LoadObjectError</span><span class="p">,</span> <span class="n">InputValidationError</span><span class="p">,</span> <span class="n">InvalidVersionAttributeError</span>


Expand Down Expand Up @@ -123,17 +123,7 @@ <h1>Source code for versionedobj.serializer</h1><div class="highlight"><pre>
<span class="sd"> :return: object data as a dict</span>
<span class="sd"> :rtype: dict</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="n">only</span> <span class="ow">and</span> <span class="n">ignore</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">InvalidFilterError</span><span class="p">(</span><span class="s2">&quot;Cannot use both &#39;only&#39; and &#39;ignore&#39;&quot;</span><span class="p">)</span>

<span class="n">ret</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">for</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">_walk_obj_attrs</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">only</span><span class="p">,</span> <span class="n">ignore</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">field</span><span class="o">.</span><span class="n">value</span><span class="p">,</span> <span class="n">CustomValue</span><span class="p">):</span>
<span class="n">field</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">field</span><span class="o">.</span><span class="n">value</span><span class="o">.</span><span class="n">to_dict</span><span class="p">()</span>

<span class="n">ret</span> <span class="o">=</span> <span class="n">field</span><span class="o">.</span><span class="n">set_dict_field</span><span class="p">(</span><span class="n">ret</span><span class="p">)</span>

<span class="k">return</span> <span class="n">ret</span></div>
<span class="k">return</span> <span class="n">_obj_to_dict</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">only</span><span class="p">,</span> <span class="n">ignore</span><span class="p">)</span></div>

<div class="viewcode-block" id="Serializer.validate_dict"><a class="viewcode-back" href="../../versionedobj.html#versionedobj.serializer.Serializer.validate_dict">[docs]</a> <span class="k">def</span> <span class="nf">validate_dict</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">,</span> <span class="n">attrs</span><span class="p">,</span> <span class="n">only</span><span class="o">=</span><span class="p">[],</span> <span class="n">ignore</span><span class="o">=</span><span class="p">[]):</span>
<span class="sd">&quot;&quot;&quot;</span>
Expand Down
40 changes: 32 additions & 8 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,12 @@ <h1><a class="toc-backref" href="#id2">Object serialization &amp; versioning fra
<li><p><a class="reference internal" href="#validating-input-data-without-deserializing" id="id17">Validating input data without deserializing</a></p></li>
<li><p><a class="reference internal" href="#resetting-object-instance-to-default-values" id="id18">Resetting object instance to default values</a></p></li>
<li><p><a class="reference internal" href="#testing-object-instance-equality" id="id19">Testing object instance equality</a></p></li>
<li><p><a class="reference internal" href="#performance-stress-test-visualization" id="id20">Performance/stress test visualization</a></p></li>
<li><p><a class="reference internal" href="#contributions" id="id21">Contributions</a></p></li>
<li><p><a class="reference internal" href="#object-instance-hashing" id="id20">Object instance hashing</a></p></li>
<li><p><a class="reference internal" href="#performance-stress-test-visualization" id="id21">Performance/stress test visualization</a></p></li>
<li><p><a class="reference internal" href="#contributions" id="id22">Contributions</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#indices-and-tables" id="id22">Indices and tables</a></p></li>
<li><p><a class="reference internal" href="#indices-and-tables" id="id23">Indices and tables</a></p></li>
</ul>
</div>
<div class="section" id="installing">
Expand Down Expand Up @@ -495,7 +496,7 @@ <h2><a class="toc-backref" href="#id18">Resetting object instance to default val
</div>
<div class="section" id="testing-object-instance-equality">
<h2><a class="toc-backref" href="#id19">Testing object instance equality</a><a class="headerlink" href="#testing-object-instance-equality" title="Permalink to this headline"></a></h2>
<p>You can test whether two <code class="docutils literal notranslate"><span class="pre">VersionedObject</span></code> instances are equal in both structure and,
<p>You can test whether two <code class="docutils literal notranslate"><span class="pre">VersionedObject</span></code> instances are equal in both structure and
values, the same way in which you would check equality of any other two objects:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">versionedobj</span> <span class="kn">import</span> <span class="n">VersionedObject</span>

Expand Down Expand Up @@ -523,8 +524,30 @@ <h2><a class="toc-backref" href="#id19">Testing object instance equality</a><a c
<li><p>Both objects contain matching attribute names and values</p></li>
</ul>
</div>
<div class="section" id="object-instance-hashing">
<h2><a class="toc-backref" href="#id20">Object instance hashing</a><a class="headerlink" href="#object-instance-hashing" title="Permalink to this headline"></a></h2>
<p>Objects can be uniquely hashed based on their instance attribute values, using the builtin
<code class="docutils literal notranslate"><span class="pre">hash()</span></code> function. This means, for example, that you can use object instances as dict keys:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">versionedobj</span> <span class="kn">import</span> <span class="n">VersionedObject</span>

<span class="k">class</span> <span class="nc">Person</span><span class="p">(</span><span class="n">VersionedObject</span><span class="p">):</span>
<span class="n">name</span> <span class="o">=</span> <span class="s2">&quot;sam&quot;</span>
<span class="n">age</span> <span class="o">=</span> <span class="mi">31</span>

<span class="n">p1</span> <span class="o">=</span> <span class="n">Person</span><span class="p">()</span>
<span class="n">p2</span> <span class="o">=</span> <span class="n">Person</span><span class="p">()</span>

<span class="c1"># Change 1 value on p2 so the hash value is different</span>
<span class="n">p2</span><span class="o">.</span><span class="n">age</span> <span class="o">=</span> <span class="mi">32</span>

<span class="n">d</span> <span class="o">=</span> <span class="p">{</span><span class="n">p1</span><span class="p">:</span> <span class="s2">&quot;a&quot;</span><span class="p">,</span> <span class="n">p2</span><span class="p">:</span> <span class="s2">&quot;b&quot;</span><span class="p">}</span>
<span class="nb">print</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
<span class="c1"># { Person({&quot;name&quot;: &quot;sam&quot;, &quot;age&quot;: 31}): &quot;a&quot;, Person({&quot;name&quot;: &quot;sam&quot;, &quot;age&quot;: 32}): &quot;b&quot; }</span>
</pre></div>
</div>
</div>
<div class="section" id="performance-stress-test-visualization">
<h2><a class="toc-backref" href="#id20">Performance/stress test visualization</a><a class="headerlink" href="#performance-stress-test-visualization" title="Permalink to this headline"></a></h2>
<h2><a class="toc-backref" href="#id21">Performance/stress test visualization</a><a class="headerlink" href="#performance-stress-test-visualization" title="Permalink to this headline"></a></h2>
<p>The following image is generated by the <code class="docutils literal notranslate"><span class="pre">tests/performance_tests/big_class_performance_test.py</span></code> script,
which creates multiple versioned objects of increasing size.</p>
<p>The time taken to serialize each object to a dict, and also to deserialize the object data
Expand All @@ -536,18 +559,19 @@ <h2><a class="toc-backref" href="#id20">Performance/stress test visualization</a
<img alt="https://github.com/eriknyquist/versionedobj/raw/master/images/performance_graph.png" src="https://github.com/eriknyquist/versionedobj/raw/master/images/performance_graph.png" />
</div>
<div class="section" id="contributions">
<h2><a class="toc-backref" href="#id21">Contributions</a><a class="headerlink" href="#contributions" title="Permalink to this headline"></a></h2>
<h2><a class="toc-backref" href="#id22">Contributions</a><a class="headerlink" href="#contributions" title="Permalink to this headline"></a></h2>
<p>Contributions are welcome, please open a pull request at <a class="reference external" href="https://github.com/eriknyquist/versionedobj">https://github.com/eriknyquist/versionedobj</a> and ensure that:</p>
<ol class="arabic simple">
<li><p>All existing unit tests pass (run tests via <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">setup.py</span> <span class="pre">test</span></code>)</p></li>
<li><p>New unit tests are added to cover any modified/new functionality</p></li>
<li><p>New unit tests are added to cover any modified/new functionality (run <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">code_coverage.py</span></code>
to ensure that coverage is above 98%)</p></li>
</ol>
<p>If you have any questions about / need help with contributions or unit tests, please
contact Erik at <a class="reference external" href="mailto:eknyquist&#37;&#52;&#48;gmail&#46;com">eknyquist<span>&#64;</span>gmail<span>&#46;</span>com</a>.</p>
</div>
</div>
<div class="section" id="indices-and-tables">
<h1><a class="toc-backref" href="#id22">Indices and tables</a><a class="headerlink" href="#indices-and-tables" title="Permalink to this headline"></a></h1>
<h1><a class="toc-backref" href="#id23">Indices and tables</a><a class="headerlink" href="#indices-and-tables" title="Permalink to this headline"></a></h1>
<ul class="simple">
<li><p><a class="reference internal" href="genindex.html"><span class="std std-ref">Index</span></a></p></li>
<li><p><a class="reference internal" href="py-modindex.html"><span class="std std-ref">Module Index</span></a></p></li>
Expand Down
Loading

0 comments on commit 497d9ef

Please sign in to comment.