Skip to content

Commit

Permalink
closes #38 by removing spectate.core to simplify maintenance (#40)
Browse files Browse the repository at this point in the history
* closes #38 by removing spectate.core to simplify maintenance

* remove docs for spectate.core
  • Loading branch information
rmorshea authored May 11, 2020
1 parent fbe9f7b commit 86df9c5
Show file tree
Hide file tree
Showing 21 changed files with 125 additions and 912 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# PyEnv
.python-version

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
4 changes: 0 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@ matrix:
python: 3.7
env:
- TEST_CMD="flake8"
- name: "python-2.7"
python: 2.7
- name: "python-3.5"
python: 3.5
- name: "python-3.6"
python: 3.6
- name: "python-3.7"
Expand Down
1 change: 0 additions & 1 deletion docs/source/usage/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,3 @@ Usage
events
builtins
create-models
low-level-usage
111 changes: 0 additions & 111 deletions docs/source/usage/low-level-usage.rst

This file was deleted.

4 changes: 1 addition & 3 deletions spectate/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
__version__ = "0.4.1" # evaluated in setup.py

from .core import * # noqa
__version__ = "0.5.0" # evaluated in setup.py
68 changes: 39 additions & 29 deletions spectate/mvc/base.py → spectate/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
from contextlib import contextmanager
from weakref import WeakValueDictionary

from spectate.core import Watchable, watched, Immutable, MethodSpectator

from .utils import members
from .utils import Immutable


__all__ = ["Model", "Control", "view", "unview", "views", "link", "unlink", "notifier"]
Expand Down Expand Up @@ -209,7 +207,7 @@ def __init__(
elif isinstance(methods, str):
self.methods = tuple(map(str.strip, methods.split(",")))
else:
raise ValueError("methods must be a string of list of strings")
raise ValueError("methods must be a string or list of strings")
self.name = None
if isinstance(before, Control):
before = before._before
Expand All @@ -233,7 +231,35 @@ def __set_name__(self, cls, name):
else:
self.name = name
for m in self.methods:
setattr(cls, m, MethodSpectator(getattr(cls, m), m))
setattr(cls, m, self._create_controlled_method(cls, m))

def _create_controlled_method(self, cls, name):
method = getattr(cls, name)

@wraps(method)
def wrapped_method(obj, *args, **kwargs):
cls = type(obj)
bound_control = self.__get__(obj, cls)

before_control = bound_control.before
if before_control is not None:
before_value = before_control(
obj, Immutable(name=name, args=args, kwargs=kwargs)
)
else:
before_value = None

result = method.__get__(obj, cls)(*args, **kwargs)

after_control = bound_control.after
if after_control is not None:
after_control(
obj, Immutable(before=before_value, name=name, value=result)
)

return result

return wrapped_method


class BoundControl:
Expand Down Expand Up @@ -293,7 +319,7 @@ def afterback(value, answer):
return afterback


class Model(Watchable):
class Model:
"""An object that can be :class:`controlled <Control>` and :func:`viewed <view>`.
Users should define :class:`Control` methods and then :func:`view` the change
Expand Down Expand Up @@ -332,34 +358,18 @@ def _control_after_attr_change(self, answer, notify):
def printer(o, events):
for e in events:
print(e)
o.a = 1
o.b = 2
.. code-block:: text
{'attr': 'a', 'old': Undefined, 'new': 1}
{'attr': 'b', 'old': Undefined, 'new': 2}
"""

_model_controls = ()

def __init_subclass__(cls, **kwargs):
controls = []
for k, v in members(cls):
if isinstance(v, Control):
controls.append(k)
cls._model_controls = tuple(controls)
super().__init_subclass__(**kwargs)

def __new__(cls, *args, **kwargs):
self, spectator = watched(super().__new__, cls)
for name in cls._model_controls:
ctrl = getattr(self, name)
for method in ctrl.methods:
spectator.callback(method, ctrl.before, ctrl.after)
new = super().__new__
if new is not object.__new__:
self = new(cls, *args, **kwargs)
else:
self = new(cls)

object.__setattr__(self, "_model_views", [])
object.__setattr__(self, "_inner_models", WeakValueDictionary())

return self

def _attach_child_model(self, model):
Expand Down
Loading

0 comments on commit 86df9c5

Please sign in to comment.