class ReadOnlyTest(Atom): r = ReadOnly()
class A(Atom): m = member assert A.m.delattr_mode[0] == DelAttr.NoOp a = A() a.m = 1 del a.m assert a.m == 1 assert A.m.do_delattr(a) is None assert a.m == 1 @pytest.mark.parametrize("member, mode", [(Event(), DelAttr.Event), (Signal(), DelAttr.Signal), (ReadOnly(), DelAttr.ReadOnly), (Constant(1), DelAttr.Constant) ]) def test_undeletable(member, mode): """Test that unsettable members do raise the proper error. """ class Undeletable(Atom): m = member assert Undeletable.m.delattr_mode[0] == mode u = Undeletable() with pytest.raises(TypeError): del u.m with pytest.raises(TypeError):
(Constant(1), "Constant")]) def test_unsettable(member, mode): """Test that unsettable members do raise the proper error.""" class Unsettable(Atom): m = member u = Unsettable() assert u.get_member("m").setattr_mode[0] == getattr(SetAttr, mode) with pytest.raises(TypeError) as excinfo: u.m = 1 assert mode.lower() in excinfo.exconly() @pytest.mark.parametrize("member, mode", [(Int(), "Slot"), (ReadOnly(), "ReadOnly")]) def test_wrong_index_value(member, mode): """Test handling wrong index This should never happen save if the user manipulate the index. """ class Unsettable(Atom): m = member Unsettable.m.set_index(100) u = Unsettable() assert u.get_member("m").setattr_mode[0] == getattr(SetAttr, mode) with pytest.raises(AttributeError) as excinfo: u.m = 1
class Operative(Backbone): """Adds functionality for auto showing to Backbone""" name = ReadOnly().tag( private=True, desc= "Name of agent. This name will be modified to be unique, if necessary", initialized=False) #def _default_name(self): # return self.base_name #def _observe_name(self, change): # check_initialized(self, change) desc = Unicode().tag(private=True, desc="Optional description of agent") saving = False save_file = None base_name = "operative" @classmethod def process_kwargs(cls, kwargs): agent = kwargs.pop(cls.base_name, None) if agent is None: return cls() return agent timeout = Float(1).tag(sub=True, desc="Timeout in seconds") @private_property def abort_timeout(self): return 1.0 busy = Bool(False).tag( private=True, desc="A private Bool that represents if the agent is busy") progress = Int(0).tag( private=True, desc="A private Int that represents progress from 0 to 100") abort = Bool(False).tag( private=True, desc="A private Bool that signifies the agent wants to abort") thread = Typed(Thread).tag( private=True, desc="A private Typed that links to the current thread") queue = Instance(Queue).tag( private=True, desc="A private Instance that links to the agent's Queue") done = Event().tag(private=True, desc="A private Event that signifies a thread is done") thread_list = ContainerList().tag( private=True, desc="A private ContainerList that has the list of threads") def _default_queue(self): """queue of length one""" return Queue(1) def lins(self, start, stop, nsteps): """A utility generator for looping with abort and progress. Use like linspace""" n = start for n in linspace(start, stop, nsteps): if self.abort: break safe_setattr(self, "progress", int((n - start) / (stop - start) * 100)) yield n yield n def loop(self, start, stop=None, step=1): """a utility generator for looping with abort and progress. Use like range""" if stop is None: stop = start start = 0 n = start for n in range(start, stop, step): if self.abort: break safe_setattr(self, "progress", int((n + 1.0) * step / (stop - start) * 100.0)) yield n yield n def queue_put(self, result): """adds result to queue if thread is active and returns result. blocks for self.timeout seconds""" if self.thread is not None: self.queue.put(result, timeout=self.abort_timeout) return result def thread_run(self, code, *args, **kwargs): """assisting function for running threads that passes exceptions and activates done event when finished""" try: return self.queue_put(code(*args, **kwargs)) except Exception as e: self.queue_put(e) finally: self.done() def _observe_done(self, change): self.stop_thread() def stop_thread(self): """function for stopping a thread. if there are more threads in thread_list, it activates the next one. otherwise sets thread, abort, and busy to false""" print "stopping thread: " + self.thread.name if self.thread is not None: try: value = self.queue.get(timeout=self.abort_timeout) if isinstance(value, Exception): raise value if hasattr(self, self.thread.name): setattr(self, self.thread.name, value) elif hasattr(value, "show"): safe_call(value.show) safe_call( self.chief_window.get_member("agent_win_dict").reset, self.chief_window) finally: if self.thread_list != []: self.start_thread() else: self.busy = False self.thread = None self.abort = False return value def start_thread(self): """starts first thread in thread_list and sets busy to true""" self.busy = True self.thread = self.thread_list.pop(0) print "starting thread: " + self.thread.name self.thread.start() def add_thread(self, name, code, *args, **kwargs): """adds a thread to thread_list and starts it if none are running""" thread = Thread(target=self.thread_run, args=(code, ) + args, kwargs=kwargs) #, args=(self.loop_step, 10)) thread.name = name self.thread_list.append(thread) if self.thread is None: self.start_thread() def _observe_abort(self, change): """observer for abort, logs abort""" if self.abort: if self.busy: log_debug("ABORTED: {0}".format(self.name)) else: self.abort = False @classmethod def abort_all(cls): """attempts to abort all instruments""" for instr in cls.agent_dict.values(): instr.abort = True def show(self, *args, **kwargs): """shortcut to shower which defaults to shower(self)""" shower(*((self, ) + args), **kwargs) @classmethod def clean_up(cls): """Default class clean up aborts all processes and flushes class file buffer if saving""" cls.abort_all() if cls.saving: if hasattr(cls, "save_file"): cls.save_file.flush_buffers() @classmethod def run_all(cls): """Runs all functions added in run_func_dict". Can be included in cls_run_funcs""" for func in cls.run_func_dict.values(): if func != cls.run_all: func() @private_property def plots(self): """Dictionary of plots determined by base_name of agent being 'plot'""" return OrderedDict([(name, agent) for (name, agent) in self.agent_dict.iteritems() if agent.base_name == "plot"]) @classmethod def get_agents(cls, *AgentTypes): """returns an OrderedDict of all agents in agent_dict of a particular AgentTypes. AgentType defaults to just type of self if no args are passed""" if AgentTypes is (): AgentTypes = (cls, ) #(type(cls),) return OrderedDict([(name, agent) for (name, agent) in cls.agent_dict.iteritems() if any(isinstance(agent, s) for s in AgentTypes)]) agent_dict = OrderedDict() run_func_dict = OrderedDict() @classmethod def add_func(cls, *funcs): """Adds functions to run_func_dict. functions should be a classmethod, a staticmethod or a separate function that takes no arguments""" for func in funcs: cls.run_func_dict[func.func_name] = func if len(funcs) > 0: return funcs[0] @private_property def cls_run_funcs(self): """class or static methods to include in run_func_dict on initialization. Can be overwritten in child classes""" return [] @classmethod def activated(cls): """Function that runs when window is activated.""" pass def __init__(self, **kwargs): """extends Backbone __init__ to add agent to boss's agent list and give unique default name.""" agent_name = defaulter(self, "name", kwargs) agent_name = name_generator(agent_name, Operative.agent_dict, self.base_name) #if agent_name in Operative.agent_dict: # agent_name="{name}__{num}".format(name=agent_name, num=len(Operative.agent_dict)) self.name = agent_name Operative.agent_dict[self.name] = self #set_tag(self, "name", initialized=False) super(Operative, self).__init__(**kwargs) #set_tag(self, "name", initialized=True) self.add_func(*self.cls_run_funcs)
"""Test that unsettable members do raise the proper error. """ class Unsettable(Atom): m = member u = Unsettable() assert u.get_member('m').setattr_mode[0] == getattr(SetAttr, mode) with pytest.raises(TypeError) as excinfo: u.m = 1 assert mode.lower() in excinfo.exconly() @pytest.mark.parametrize("member, mode", [(Int(), 'Slot'), (ReadOnly(), 'ReadOnly')]) def test_wrong_index_value(member, mode): """Test handling wrong index This should never happen save if the user manipulate the index. """ class Unsettable(Atom): m = member Unsettable.m.set_index(100) u = Unsettable() assert u.get_member('m').setattr_mode[0] == getattr(SetAttr, mode) with pytest.raises(AttributeError) as excinfo: u.m = 1
class PlotFormat(PlotUpdate): """base class corresponding to one graph or collection on axes""" plot_name=ReadOnly() #def _default_plot_name(self): # return self.plot_type #def _observe_plot_name(self, change): # check_initialized(self, change) append=Bool(False) remove=Bool(False) xcoord=Float() ycoord=Float() xind=Int() yind=Int() # x_min=Float() # x_max=Float() # y_min=Float() # y_max=Float() # # def _default_x_min(self): # return min(self.xdata) # # def _default_x_max(self): # return max(self.xdata) # # def _default_y_min(self): # return min(self.ydata) # # def _default_y_max(self): # return max(self.ydata) def do_autolim(self): if self.plotter.auto_xlim: self.plotter.x_min=float(min((self.plotter.x_min, nanmin(self.xdata)))) self.plotter.x_max=float(max((self.plotter.x_max, nanmax(self.xdata)))) if self.plotter.auto_ylim: self.plotter.y_min=float(min((self.plotter.y_min, nanmin(self.ydata)))) self.plotter.y_max=float(max((self.plotter.y_max, nanmax(self.ydata)))) xdata=Array2() ydata=Array2() plot_type=Enum("line", "scatter", "multiline", "colormap", "vline", "hline", "polygon", "cross_cursor") clt=Typed(Line2D) visible=Bool(True).tag(former="visible") def clt_values(self): if isinstance(self.clt, dict): return self.clt.values() return [self.clt] def plot_set(self, param): for clt in self.clt_values(): simple_set(clt, self, get_tag(self, param, "former", param)) @plot_observe("visible") def plot_update(self, change): """set the clt's parameter to the obj's value using clt's set function""" self.plot_set(change["name"]) def remove_collection(self): if self.remove: if self.clt is not None: self.clt.remove() def __init__(self, **kwargs): plot_name=defaulter(self, "plot_name", kwargs) plotter=kwargs["plotter"] #if plot_name in plotter.plot_dict: # if self.remove: # self.remove_collection() # else: plot_name=name_generator(plot_name, plotter.plot_dict, kwargs.get("plot_type", self.plot_type)) self.plot_name=plot_name super(PlotFormat, self).__init__(**kwargs) #if plot_name is None: # plot_name=self.plot_type #if agent_name in Operative.agent_dict: # agent_name="{name}__{num}".format(name=agent_name, num=len(Operative.agent_dict)) #kwargs["name"]=agent_name #Operative.agent_dict[agent_name]=self # plot_name+="__{0}".format(len(self.plotter.plot_dict.keys())) #self.plot_name=plot_name #set_tag(self, "plot_name", initialized=False) #if self.plot_name=="": # self.plot_name=self.plot_type #if self.plot_name in self.plotter.plot_dict: # if self.remove: # self.remove_collection() # else: # self.plot_name+="__{0}".format(len(self.plotter.plot_dict.keys())) self.plotter.plot_dict[self.plot_name]=self #set_tag(self, "plot_name", initialized=True) @cached_property def view_window(self): with imports(): from plot_format_e import Main view=Main(pltr=self.plotter) return view
class PlotFormat(PlotUpdate): """base class corresponding to one graph or collection on axes""" plot_name = ReadOnly() append = Bool(False) remove = Bool(False) xcoord = Float() ycoord = Float() xind = Int() yind = Int() # x_min=Float() # x_max=Float() # y_min=Float() # y_max=Float() # # def _default_x_min(self): # return min(self.xdata) # # def _default_x_max(self): # return max(self.xdata) # # def _default_y_min(self): # return min(self.ydata) # # def _default_y_max(self): # return max(self.ydata) def do_autolim(self): if self.plotter.auto_xlim: self.plotter.x_min = float( min((self.plotter.x_min, nanmin(self.xdata)))) self.plotter.x_max = float( max((self.plotter.x_max, nanmax(self.xdata)))) else: self.plotter.set_xlim(self.plotter.x_min, self.plotter.x_max) if self.plotter.auto_ylim: self.plotter.y_min = float( min((self.plotter.y_min, nanmin(self.ydata)))) self.plotter.y_max = float( max((self.plotter.y_max, nanmax(self.ydata)))) else: self.plotter.set_ylim(self.plotter.y_min, self.plotter.y_max) if self.plotter.show_legend: self.plotter.legend() xdata = Array() ydata = Array() plot_type = Enum("line", "scatter", "multiline", "colormap", "vline", "hline", "polygon", "cross_cursor") clt = Typed(Line2D) visible = Bool(True).tag(former="visible") def clt_values(self): if isinstance(self.clt, dict): return self.clt.values() return [self.clt] def plot_set(self, param): for clt in self.clt_values(): simple_set(clt, self, get_tag(self, param, "former", param)) @plot_observe("visible") def plot_update(self, change): """set the clt's parameter to the obj's value using clt's set function""" self.plot_set(change["name"]) def remove_collection(self): if self.remove: if self.clt is not None: self.clt.remove() def __init__(self, **kwargs): plot_name = kwargs.pop( "plot_name", self.plot_type) #defaulter(self, "plot_name", kwargs) plotter = kwargs["plotter"] self.plot_name = name_generator( plot_name, plotter.plot_dict, kwargs.get("plot_type", self.plot_type)) super(PlotFormat, self).__init__(**kwargs) self.plotter.plot_dict[self.plot_name] = self @cached_property def view_window(self): with imports(): from plot_format_e import Main view = Main(pltr=self.plotter) return view
m = Value() m.set_validate_mode(Validate.NoOp, None) for value in (1, 1.0, "", [], {}): assert m.do_validate(a, None, value) == value def c(x: object) -> int: return int(str(x), 2) @pytest.mark.parametrize( "member, set_values, values, raising_values", [ (Value(), ["a", 1, None], ["a", 1, None], []), (ReadOnly(int), [1], [1], [1.0]), (Bool(), [True, False], [True, False], "r"), (Int(strict=True), [1], [1], [1.0]), (Int(strict=False), [1, 1.0, int(1)], 3 * [1], ["a"]), (Range(0, 2), [0, 2], [0, 2], [-1, 3, ""]), (Range(2, 0), [0, 2], [0, 2], [-1, 3]), (Range(0), [0, 3], [0, 3], [-1]), (Range(high=2), [-1, 2], [-1, 2], [3]), ( Range(sys.maxsize, sys.maxsize + 2), [sys.maxsize, sys.maxsize + 2], [sys.maxsize, sys.maxsize + 2], [sys.maxsize - 1, sys.maxsize + 3], ), (Float(), [1, int(1), 1.1], [1.0, 1.0, 1.1], [""]), (Float(strict=True), [1.1], [1.1], [1]),