Skip to content

Commit

Permalink
more docs + no more Immutable
Browse files Browse the repository at this point in the history
the Immutable object was always a bad idea
also bumps version to 1.0 - after this I think we will put this in maintenance mode
  • Loading branch information
rmorshea committed Dec 4, 2020
1 parent 8925f2f commit 68703b9
Show file tree
Hide file tree
Showing 27 changed files with 355 additions and 394 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# IDE
.vscode
.idea

# PyEnv
.python-version

Expand Down Expand Up @@ -60,3 +64,4 @@ target/

.ipynb_checkpoints
.pytest_cache
Untitled*.ipynb
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

# Spectate

A library for Python 2 and 3 that can track changes to mutable data types.
A library for Python 3.6 and above that can track changes to mutable data types.

With `spectate`, complicated protocols for managing updates don't need to be the outward responsibility of a user and can instead be done automagically in the background. For instance, syncing the state between a server and client can controlled by `spectate`, so users don't have to.

Expand Down
2 changes: 1 addition & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ and can instead be done automagically in the background.

install
usage/index
api/index
api

At A Glance
-----------
Expand Down
79 changes: 0 additions & 79 deletions docs/source/usage/basics.rst

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ Builtin Model Types

Spectate provides a number of builtin model types that you can use out of the box.
For most users these built-in types should be enough, however if you're adventurous,
then you can :ref:`define your own models <Creating Models>`.
then you can create your own :ref:`Custom Models`.


Dictionary
''''''''''
----------

The :class:`~spectate.models.Dict` model is a subclass of Python's standard
:class:`dict`. This will produce events when the value of a key in the dictionary
Expand Down Expand Up @@ -35,7 +35,7 @@ Events produced by :class:`~spectate.models.Dict` have the following fields:


List
''''
----

The :class:`~spectate.models.List` model is a subclass of Python's standard
:class:`list`. This model will produce events when an element of the list changes
Expand Down Expand Up @@ -64,7 +64,7 @@ normal syntax to set or delete an item. Events produced by


Set
'''
---

The :class:`~spectate.models.Set` model is a subclass of Python's standard
:class:`set`. This model will produce events when an element of the set changes.
Expand All @@ -86,7 +86,7 @@ Events produced by :class:`~spectate.models.Set` have the following keys:


Object
''''''
------

The :class:`~spectate.models.Object` model is a subclass of Python's standard
:class:`object`. This model will produce events when an attribute of the object changes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ modify events before they are distributed to views. This allows you to
edge cases in your code, improving performance by :ref:`merging <Merging Events>`
events, or :ref:`undo <Rolling Back Changes>` unwanted changes.


Holding Events
--------------

Expand Down Expand Up @@ -160,8 +161,8 @@ be distributed:
l.append(1)
Force Notifying
---------------
Manually Notifying
------------------

At times, and more likely when writing tests, you may need to forcefully send an event
to a model. This can be achieved using the :func:`~spectate.base.notifier` context
Expand Down
8 changes: 4 additions & 4 deletions docs/source/usage/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Usage
.. toctree::
:maxdepth: 2

basics
events
builtins
create-models
the-basics
handling-events
builtin-model-types
spectating-other-types
Original file line number Diff line number Diff line change
@@ -1,17 +1,31 @@
Creating Models
===============

Creating models requires you to define a :class:`~spectate.base.Model` subclass
which has :class:`~spectate.base.Control` objects assigned to it. Each control
object is responsible for observing calls to particular methods on the model class.
For example, if you wanted to know when an element was appended to a list you might
observe the ``append`` method.
Spectating Other Types
======================

In a prior example demonstrating how to create :ref:`a custom model <Custom Models>` we
used :func:`~spectate.base.notifier` to produce events. This is sufficient in most cases,
but sometimes you arent' able to manually trigger
events from within a method. This might occur when inheriting from a builtin type
(e.g. ``list``, ``dict``, etc) that is implemented in C or a third party package that
doesn't use ``spectate``. In those cases, you must wrap an existing method and are
religated to producing events before and/or after it gets called.

In these scenarios you must define a :class:`~spectate.base.Model` subclass which has
:class:`~spectate.base.Control` objects assigned to it. Each control object is
responsible for observing calls to particular methods on the model class. For example,
if you wanted to know when an element was appended to a list you might observe the
``append`` method.

To show how this works we will implement a simple counter with the goal of knowing when
the value in the counter has incremented or decremented. To get started we should create
a ``Counter`` class which inherits from :class:`~spectate.base.Model` and define
its ``increment`` and ``decrement`` methods normally:

.. note::

Usually if you're using :class:`~spectate.base.Control` objects you'd do it with
`multiple inheritance <https://docs.python.org/3/tutorial/classes.html#multiple-inheritance>`__,
but to keep things simple we aren't doing that in the following examples.

.. code-block:: python
from spectate import mvc
Expand Down Expand Up @@ -129,12 +143,12 @@ No lets see what happens we can call ``increment`` or ``decrement``:
<function BoundControl.after.<locals>.afterback.<locals>.notify at 0x7f9ce57e89d8>
Model Callbacks
---------------
Control Callbacks
-----------------

The callback pair we registered to our ``Counter`` when learning how to
:ref:`define controls <Adding Model Controls>`, hereafter referred to as
:ref:`"beforebacks" <Model Beforebacks>` and :ref:`"afterbacks" <Model Afterbacks>`
:ref:`"beforebacks" <Control Beforebacks>` and :ref:`"afterbacks" <Control Afterbacks>`
are how event information is communicated to views. Defining both a beforeback and
an afterback is not required, but doing so allows for a beforeback to pass data to its
corresponding afterback which in turn makes it possible to compute the difference
Expand Down Expand Up @@ -163,16 +177,16 @@ between the state before and the state after a change takes place:
def _before_change(self, call, notify):
amount = call.parameters()["amount"]
print("value will %s by %s" % (call.name, amount))
print(f"value will {call['name']} by {amount}")
old_value = self.value
return old_value
def _after_change(self, answer, notify):
old_value = answer.before # this was returned by `_before_change`
old_value = answer["before"] # this was returned by `_before_change`
new_value = self.value
print("the old value was %r" % old_value)
print("the new value is %r" % new_value)
print("the value changed by %r" % (new_value - old_value))
print(f"the old value was {old_value})
print(f"the new value is {new_value})
print(f"the value changed by {new_value - old_value}")
Now we can try incrementing and decrementing as before:

Expand All @@ -194,7 +208,7 @@ Now we can try incrementing and decrementing as before:
the value changed by -1
Sending Event Notifications
Control Event Notifications
---------------------------

We're now able to use :ref:`"beforebacks" <Model Beforebacks>` and
Expand Down Expand Up @@ -228,12 +242,12 @@ things simple we'll just replace our ``print`` statements with calls to ``notify
def _before_change(self, call, notify):
amount = call.parameters()["amount"]
notify(message="value will %s by %s" % (call.name, amount))
notify(message="value will %s by %s" % (call["name"], amount))
old_value = self.value
return old_value
def _after_change(self, answer, notify):
old_value = answer.before # this was returned by `_before_change`
old_value = answer["before"] # this was returned by `_before_change`
new_value = self.value
notify(message="the old value was %r" % old_value)
notify(message="the new value is %r" % new_value)
Expand Down Expand Up @@ -265,8 +279,8 @@ To print out the same messages as before we'll need to register a view with out
the value changed by -1
Model Beforebacks
-----------------
Control Beforebacks
-------------------

Have a signature of ``(call, notify) -> before``

Expand All @@ -292,8 +306,8 @@ Have a signature of ``(call, notify) -> before``
+ ``before`` is a value which gets passed on to its respective :ref:`afterback <Model Afterbacks>`.


Model Afterbacks
----------------
Control Afterbacks
------------------

Have a signature of ``(answer, notify)``

Expand Down
Loading

0 comments on commit 68703b9

Please sign in to comment.