API¶
-
class
spectate.models.
Dict
(*args: Any, **kwargs: Any)[source]¶ A
spectate.mvc
enableddict
.-
clear
() → None. Remove all items from D.¶
-
pop
(k[, d]) → v, remove specified key and return the corresponding value.¶ If key is not found, d is returned if given, otherwise KeyError is raised
-
setdefault
(key, default=None, /)¶ Insert key with a value of default if key is not in the dictionary.
Return the value for key if key is in the dictionary, else default.
-
update
([E, ]**F) → None. Update D from dict/iterable E and F.¶ If E is present and has a .keys() method, then does: for k in E: D[k] = E[k] If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]
-
-
class
spectate.models.
List
(*args: Any, **kwargs: Any)[source]¶ A
spectate.mvc
enabledlist
.-
append
(object, /)¶ Append object to the end of the list.
-
clear
()¶ Remove all items from list.
-
extend
(iterable, /)¶ Extend list by appending elements from the iterable.
-
insert
(index, object, /)¶ Insert object before index.
-
pop
(index=-1, /)¶ Remove and return item at index (default last).
Raises IndexError if list is empty or index is out of range.
-
remove
(value, /)¶ Remove first occurrence of value.
Raises ValueError if the value is not present.
-
reverse
()¶ Reverse IN PLACE.
-
sort
(*, key=None, reverse=False)¶ Stable sort IN PLACE.
-
-
class
spectate.models.
Set
(*args: Any, **kwargs: Any)[source]¶ A
spectate.mvc
enabledset
.-
add
()¶ Add an element to a set.
This has no effect if the element is already present.
-
clear
()¶ Remove all elements from this set.
-
difference_update
()¶ Remove all elements of another set from this set.
-
discard
()¶ Remove an element from a set if it is a member.
If the element is not a member, do nothing.
-
intersection_update
()¶ Update a set with the intersection of itself and another.
-
pop
()¶ Remove and return an arbitrary set element. Raises KeyError if the set is empty.
-
remove
()¶ Remove an element from a set; it must be a member.
If the element is not a member, raise a KeyError.
-
symmetric_difference_update
()¶ Update a set with the symmetric difference of itself and another.
-
update
()¶ Update a set with the union of itself and others.
-
-
class
spectate.base.
Control
(methods, *, before=None, after=None)[source]¶ An object used to define control methods on a
Model
A “control” method on a
Model
is one which reacts to another method being called. For example there is a control method on theList
which responds whenappend()
is called.A control method is a slightly modified beforeback or afterback that accepts an extra
notify
argument. These are added to a control object by callingControl.before()
orControl.after()
respectively. Thenotify
arugment is a function which allows a control method to send messages toviews
that are registered to aModel
.- Parameters
methods (
Union
[list
,tuple
,str
]) – The names of the methods on the model which this control will react to When they are calthrough the Nodeled. This is either a comma seperated string, or a list of strings.before (
Union
[Callable
,str
,None
]) – A control method that reacts before any of the givenmethods
are called. If given as a callable, then that function will be used as the callback. If given as a string, then the control will look up a method with that name when reacting (useful when subclassing).after (
Union
[Callable
,str
,None
]) – A control method that reacts after any of the givenmethods
are alled. If given as a callable, then that function will be used as the callback. If given as a string, then the control will look up a method with that name when reacting (useful when subclassing).
Examples
Control methods are registered to a
Control
with astr
or function. A string may refer to the name of a method on a Model while a function should be decorated under the same name as theControl
object to preserve the namespace.from spectate import mvc class X(mvc.Model): _control_method = mvc.Control("method").before("_control_before_method") def _control_before_method(self, call, notify): print("before") # Note how the method uses the same name. It # would be redundant to use a different one. @_control_a.after def _control_method(self, answer, notify): print("after") def method(self): print("during") x = X() x.method()
before during after
-
class
spectate.base.
Model
(*args: Any, **kwargs: Any)[source]¶ An object that can be
controlled
andviewed
.Users should define
Control
methods and thenview()
the change events those controls emit. This process starts by defining controls on a subclass ofModel
.Examples
from specate import mvc class Object(Model): _control_attr_change = Control( "__setattr__, __delattr__", before="_control_before_attr_change", after="_control_after_attr_change", ) def __init__(self, *args, **kwargs): for k, v in dict(*args, **kwargs).items(): setattr(self, k, v) def _control_before_attr_change(self, call, notify): return call["args"][0], getattr(self, call["args"][0], Undefined) def _control_after_attr_change(self, answer, notify): attr, old = answer["before"] new = getattr(self, attr, Undefined) if new != old: notify(attr=attr, old=old, new=new) o = Object() @mvc.view(o) def printer(o, events): for e in events: print(e)
-
spectate.base.
link
(source, *targets)[source]¶ Attach all of the source’s present and future view functions to the targets.
-
spectate.base.
notifier
(model)[source]¶ Manually send notifications to the given model.
- Parameters
model (
Model
) – The model whose views will recieve notifications- Return type
- Returns
A function whose keyword arguments become event data.
Example
m = Model() @view(m) def printer(m, events): for e in events: print(e) with notifier(m) as notify: # the view should print out this event notify(x=1, y=2)
-
spectate.base.
unlink
(source, *targets)[source]¶ Remove all of the source’s present and future view functions from the targets.
-
spectate.base.
view
(model: Model) → Callable[[_F], _F][source]¶ -
spectate.base.
view
(model: Model, function: Callable[[Model, Tuple[Dict[str, Any], …]], None]) → None A decorator for registering a callback to a model
- Parameters
model (
Model
) – the model object whose changes the callback should respond to.
Examples
from spectate import mvc items = mvc.List() @mvc.view(items) def printer(items, events): for e in events: print(e) items.append(1)
-
spectate.base.
views
(model)[source]¶ Return a model’s views keyed on what events they respond to.
Model views are added by calling
view()
on a model.
-
spectate.events.
hold
(model, reducer=None)[source]¶ Temporarilly withold change events in a modifiable list.
All changes that are captured within a “hold” context are forwarded to a list which is yielded to the user before being sent to views of the given
model
. If desired, the user may modify the list of events before the context is left in order to change the events that are ultimately sent to the model’s views.- Parameters
model (
Model
) – The model object whose change events will be temporarilly witheld.reducer (
Optional
[Callable
[[Model
,List
[Dict
[str
,Any
]]],List
[Dict
[str
,Any
]]]]) – A function for modifying the events list at the end of the context. Its signature is(model, events) -> new_events
wheremodel
is the given model,events
is the complete list of events produced in the context, and the returnednew_events
is a list of events that will actuall be distributed to views.
Notes
All changes witheld from views will be sent as a single notification. For example if you view a
specate.mvc.models.List
and itsappend()
method is called three times within ahold()
context,Examples
Note how the event from
l.append(1)
is omitted from the printed statements.from spectate import mvc l = mvc.List() mvc.view(d, lambda d, e: list(map(print, e))) with mvc.hold(l) as events: l.append(1) l.append(2) del events[0]
{'index': 1, 'old': Undefined, 'new': 2}
-
spectate.events.
mute
(model)[source]¶ Block a model’s views from being notified.
All changes within a “mute” context will be blocked. No content is yielded to the user as in
hold()
, and the views of the model are never notified that changes took place.- Parameters
mode – The model whose change events will be blocked.
Examples
The view is never called due to the
mute()
context:from spectate import mvc l = mvc.List() @mvc.view(l) def raises(events): raise ValueError("Events occured!") with mvc.mute(l): l.append(1)
-
spectate.events.
rollback
(model, undo=None, reducer=None)[source]¶ Withold events if an error occurs.
Generall operate
- Parameters
model (
Model
) – The model object whose change events may be witheld.undo (
Optional
[Callable
[[Model
,Tuple
[Dict
[str
,Any
], …],Exception
],None
]]) – An optional function for reversing any changes that may have taken place. Its signature is(model, events, error)
wheremodel
is the given model,events
is a list of all the events that took place, anderror
is the exception that was riased. Any changes that you make to the model within this function will not produce events.
Examples
Simple supression of events:
from spectate import mvc d = mvc.Dict() @mvc.view(d) def should_not_be_called(d, events): # we never call this view assert False try: with mvc.rollback(d): d["a"] = 1 d["b"] # key doesn't exist except KeyError: pass
Undo changes for a dictionary:
from spectate import mvc def undo_dict_changes(model, events, error): seen = set() for e in reversed(events): if e.old is mvc.Undefined: del model[e.key] else: model[e.key] = e.old try: with mvc.rollback(d, undo=undo_dict_changes): d["a"] = 1 d["b"] = 2 print(d) d["c"] except KeyError: pass print(d)
{'a': 1, 'b': 2} {}
A modules which exports specate’s Model-View-Controller utilities in a common namespace
For more info: