From 0049296544140e872f5fc71630b637dbe2ce4a9d Mon Sep 17 00:00:00 2001 From: Capocchi L Date: Thu, 28 May 2020 14:52:12 +0200 Subject: [PATCH 1/3] bug fix --- DEVSimPy-v4_0_Container.svg | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 DEVSimPy-v4_0_Container.svg diff --git a/DEVSimPy-v4_0_Container.svg b/DEVSimPy-v4_0_Container.svg deleted file mode 100644 index e69de29b..00000000 From 9285fda992eb294a5806ea15525dc9523edaa7d1 Mon Sep 17 00:00:00 2001 From: Capocchi L Date: Fri, 29 May 2020 19:53:53 +0200 Subject: [PATCH 2/3] bug fixe and wx 4.0.1 compat. --- .../pypdevs221/src/classicDEVSWrapper.py | 1 + DEVSKernel/PyPDEVS/pypdevs221/src/solver.py | 1 + Domain/Collector/MessagesCollector.py | 34 ++++++------- Domain/Collector/Plotly_For_Class.py | 8 +-- Domain/Collector/QuickScope.py | 23 ++++----- Domain/Generator/Generator.py | 5 +- Domain/Generator/RandomGenerator.py | 2 +- DomainInterface/DomainBehavior.py | 42 ++++++++++------ ImportLibrary.py | 4 +- LibraryTree.py | 49 ++++++++++--------- PreferencesGUI.py | 42 ++++++++-------- PropPanel.py | 4 +- SimulationGUI.py | 32 ++++++------ devsimpy.py | 10 ++++ requirements.txt | 2 +- 15 files changed, 134 insertions(+), 125 deletions(-) diff --git a/DEVSKernel/PyPDEVS/pypdevs221/src/classicDEVSWrapper.py b/DEVSKernel/PyPDEVS/pypdevs221/src/classicDEVSWrapper.py index e435f707..84d54a88 100644 --- a/DEVSKernel/PyPDEVS/pypdevs221/src/classicDEVSWrapper.py +++ b/DEVSKernel/PyPDEVS/pypdevs221/src/classicDEVSWrapper.py @@ -50,4 +50,5 @@ def outputFnc(self): :returns: the changed dictionary """ retval = self.model.outputFnc() + print(self.model, retval) return {i: [retval[i]] for i in retval} diff --git a/DEVSKernel/PyPDEVS/pypdevs221/src/solver.py b/DEVSKernel/PyPDEVS/pypdevs221/src/solver.py index ea480515..310d0bc2 100644 --- a/DEVSKernel/PyPDEVS/pypdevs221/src/solver.py +++ b/DEVSKernel/PyPDEVS/pypdevs221/src/solver.py @@ -223,6 +223,7 @@ def coupledOutputGenerationClassic(self, time): # Perform all selects imminent.sort() pending = imminent + level = 1 while len(pending) > 1: # Take the model each time, as we need to make sure that the selectHierarchy is valid everywhere diff --git a/Domain/Collector/MessagesCollector.py b/Domain/Collector/MessagesCollector.py index 46a33f62..f105dedc 100644 --- a/Domain/Collector/MessagesCollector.py +++ b/Domain/Collector/MessagesCollector.py @@ -38,9 +38,8 @@ def __init__(self, fileName = os.path.join(os.getcwd(),"result%d"%random.randint self.ext = ext self.comma = comma - # State variable - self.state = {'status': 'IDLE', 'sigma': INFINITY} - + self.initPhase('IDLE',INFINITY) + for np in range(10000): fn = "%s%d%s"%(self.fileName, np, self.ext) if os.path.exists(fn): @@ -52,33 +51,28 @@ def extTransition(self, *args): for port in self.IPorts: ### adapted with PyPDEVS - if hasattr(self, 'peek'): - msg = self.peek(port) - np = port.myID - else: - inputs = args[0] - msg = inputs.get(port) - np=port.port_id - + msg = self.peek(port, *args) + if msg: + np = self.getPortId(port) + ### filename - fn = "%s%d%s"%(self.fileName, np, self.ext) + fn = "%s%s%s"%(self.fileName, str(np), self.ext) with open(fn,'a') as f: f.write("%s\n"%(str(msg))) del msg - self.state["sigma"] = 0 - self.state["status"] = 'ACTIF' - return self.state + self.holdIn('ACTIF',0) + + return self.getState() ### def intTransition(self): - self.state["status"] = 'IDLE' - self.state["sigma"] = INFINITY - return self.state + self.passivateIn('IDLE') + return self.getState() ### - def timeAdvance(self):return self.state['sigma'] + def timeAdvance(self):return self.getSigma() ### - def __str__(self):return "MessagesCollector" + def __str__(self):return "MessagesCollector" \ No newline at end of file diff --git a/Domain/Collector/Plotly_For_Class.py b/Domain/Collector/Plotly_For_Class.py index 54b1e62b..2ad4831a 100644 --- a/Domain/Collector/Plotly_For_Class.py +++ b/Domain/Collector/Plotly_For_Class.py @@ -15,12 +15,8 @@ from DomainInterface.DomainBehavior import DomainBehavior from DomainInterface.Object import Message -try: - import plotly.plotly as py - import plotly.graph_objs as go -except: - import chart_studio.plotly as py - import plotly.graph_objects as go +import chart_studio.plotly as py +import plotly.graph_objects as go ### Model class ---------------------------------------------------------------- diff --git a/Domain/Collector/QuickScope.py b/Domain/Collector/QuickScope.py index 00510cbb..cbc92ca8 100644 --- a/Domain/Collector/QuickScope.py +++ b/Domain/Collector/QuickScope.py @@ -28,9 +28,6 @@ def __init__(self, fusion = True, eventAxis = False): """ DomainBehavior.__init__(self) - # State variable - self.state = {'status': 'INACTIF', 'sigma': INFINITY} - # fusioning curve self.fusion = fusion # replace time axis with step axis @@ -41,6 +38,9 @@ def __init__(self, fusion = True, eventAxis = False): self.t = INFINITY + # State variable + self.initPhase('INACTIF',INFINITY) + ### def extTransition(self, *args): """ @@ -48,12 +48,8 @@ def extTransition(self, *args): for np in range(len(self.IPorts)): ### adapted with PyPDEVS - if hasattr(self, 'peek'): - msg = self.peek(self.IPorts[np]) - else: - inputs = args[0] - msg = inputs.get(self.IPorts[np]) - + msg = self.peek(self.IPorts[np], *args) + if msg is not None: # if step axis is chosen if self.eventAxis: @@ -76,16 +72,15 @@ def extTransition(self, *args): del msg self.state['sigma'] = 0 - return self.state + return self.getState() ### def intTransition(self): - self.state["status"] = 'IDLE' - self.state["sigma"] = INFINITY - return self.state + self.passivateIn('IDLE') + return self.getState() ### - def timeAdvance(self):return self.state['sigma'] + def timeAdvance(self):return self.getSigma() ### def __str__(self):return "QuickScope" diff --git a/Domain/Generator/Generator.py b/Domain/Generator/Generator.py index bb29d9a4..09d64981 100644 --- a/Domain/Generator/Generator.py +++ b/Domain/Generator/Generator.py @@ -59,6 +59,7 @@ def intTransition(self): s = INFINITY self.state['sigma'] = s + return self.state def outputFnc(self): ### si la listValues est vide, cela veux dire qu'on veut toutes les valeurs des lignes sur une sortie @@ -69,11 +70,11 @@ def outputFnc(self): msg = Message(data, self.timeNext) i = self.__listValues.index(item) - self.poke(self.OPorts[i], msg) + return self.poke(self.OPorts[i], msg) else: data = [self.V[0].pop(0), 0.0, 0.0] msg = Message(data, self.timeNext) - self.poke(self.OPorts[0], msg) + return self.poke(self.OPorts[0], msg) def timeAdvance(self): return self.state['sigma'] diff --git a/Domain/Generator/RandomGenerator.py b/Domain/Generator/RandomGenerator.py index 9034e0b3..1bd08674 100644 --- a/Domain/Generator/RandomGenerator.py +++ b/Domain/Generator/RandomGenerator.py @@ -39,7 +39,7 @@ def outputFnc(self): """ numberMessage = random.randint(1, len(self.OPorts)) # Number message to send portsToSend = random.sample(self.OPorts, numberMessage) # The port with number message - + for port in portsToSend: value = random.randint(self.minValue, self.maxValue) self.msg.value = [value, 0.0, 0.0] diff --git a/DomainInterface/DomainBehavior.py b/DomainInterface/DomainBehavior.py index 7c2bf2ee..9f9a07be 100644 --- a/DomainInterface/DomainBehavior.py +++ b/DomainInterface/DomainBehavior.py @@ -58,7 +58,7 @@ class DomainBehavior(BaseDEVS.AtomicDEVS): """ ### - def __init__(self, name=""): + def __init__(self, name:str=""): """ Constructor. """ @@ -74,49 +74,56 @@ def __init__(self, name=""): DomainBehavior.getMsgValue = DomainBehavior.getMsgPyDEVSValue DomainBehavior.getMsgTime = DomainBehavior.getMsgPyDEVSTime DomainBehavior.getPortId = DomainBehavior.getPortIdFromPyDEVS - else: + else: DomainBehavior.peek = DomainBehavior.peekPyPDEVS DomainBehavior.poke = DomainBehavior.pokePyPDEVS DomainBehavior.getMsgValue = DomainBehavior.getMsgPyPDEVSValue DomainBehavior.getMsgTime = DomainBehavior.getMsgPyPDEVSTime DomainBehavior.getPortId = DomainBehavior.getPortIdFromPyPDEVS - def initPhase(self, phase="IDLE", sigma=0.0): + def initPhase(self, phase:str="IDLE", sigma:float=0.0)->None: self.state = {'status':phase, 'sigma':sigma} - def phaseIs(self, phase): + def setSigma(self,sigma:float=0.0)->None: + self.state['sgima'] = sigma + + def phaseIs(self, phase:str)->bool: return phase == self.state['status'] - def passivate(self): + def passivate(self)->None: self.passivateIn('passive') - def passivateIn(self, phase=""): + def passivateIn(self, phase:str="")->None: self.holdIn(phase, sigma=INFINITY) - def holdIn(self, phase="", sigma=0.0): + def holdIn(self, phase:str="", sigma:float=0.0)->None: ''' "Holding in phase " + phase + " for time " + sigma ''' self.state['status'] = phase self.state['sigma'] = sigma ### - def pokePyPDEVS(self, p, v): + def pokePyPDEVS(self, p, v)->dict: ### adapted with PyPDEVS from .Object import Message if isinstance(v, Message): v = (v.value,v.time) return {p:v} - def peekPyPDEVS(self, port, args): + def peekPyPDEVS(self, port, *args): ### adapted with PyPDEVS - #inputs = args[0] - return args.get(port) + inputs = args[0] + return inputs.get(port) + ### getters def getPortIdFromPyDEVS(self, p): return p.myID def getPortIdFromPyPDEVS(self,p): - return p.port_id + if hasattr(p, 'myID'): + return p.myID + else: + return p.port_id def getMsgPyDEVSValue(self, msg): return msg.value @@ -133,16 +140,16 @@ def getMsgPyPDEVSTime(self, msg): def getFlatComponentSet (self): return {self.name : self} - def getSigma(self): + def getSigma(self)->float: return self.state['sigma'] - def getStatus(self): + def getStatus(self)->str: return self.state['status'] - def getState(self): + def getState(self)->dict: return self.state - def __str__(self): + def __str__(self)->str: """ """ if hasattr(self, 'bloclModel'): @@ -150,6 +157,9 @@ def __str__(self): else: return self.__class__.__name__ + def __lt__(self, other): + return self.state['sigma'] > other.state['sigma'] + def main(): DB = DomainBehavior() diff --git a/ImportLibrary.py b/ImportLibrary.py index d0b22ecc..42a29316 100644 --- a/ImportLibrary.py +++ b/ImportLibrary.py @@ -286,7 +286,7 @@ def CheckDomainPath(self): def OnSelectAll(self, event): num = self._cb.GetItemCount() for i in range(num): - self._cb.CheckItem(i) + self._cb.CheckItem(i,True) def OnDeselectAll(self, event): num = self._cb.GetItemCount() @@ -418,7 +418,7 @@ def OnDelete(self, evt): def EvtCheckListBox(self, evt): index = self._cb.GetFocusedItem() label = self._cb.GetItemText(index) - + #met a jour le dico des elements selectionnes if self._cb.IsChecked(index) and label not in self._selectedItem: self._selectedItem.update({str(label):index}) diff --git a/LibraryTree.py b/LibraryTree.py index 0bd63af4..532aa20a 100644 --- a/LibraryTree.py +++ b/LibraryTree.py @@ -278,38 +278,39 @@ def OnDelete(self, evt): """ item = self.GetFocusedItem() - path = self.GetItemPyData(item) + if item.IsOk(): + path = self.GetItemPyData(item) - if path and os.path.exists(path): - ### msgbox to select what you wan to delete: file or/and item ? - db = DeleteBox(self, wx.NewIdRef(), _("Delete Options")) + if path and os.path.exists(path): + ### msgbox to select what you wan to delete: file or/and item ? + db = DeleteBox(self, wx.NewIdRef(), _("Delete Options")) - if db.ShowModal() == wx.ID_OK: + if db.ShowModal() == wx.ID_OK: - ### delete file - if db.rb2.GetValue(): - label = os.path.basename(path) - dial = wx.MessageDialog(None, _('Are you sure to delete the python file %s ?')%(label), label, wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) - if dial.ShowModal() == wx.ID_YES: - try: - ### delete file - os.remove(path) - ### delete item - self.RemoveItem(item) + ### delete file + if db.rb2.GetValue(): + label = os.path.basename(path) + dial = wx.MessageDialog(None, _('Are you sure to delete the python file %s ?')%(label), label, wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) + if dial.ShowModal() == wx.ID_YES: + try: + ### delete file + os.remove(path) + ### delete item + self.RemoveItem(item) - except Exception as info: - info = str(info) - sys.stdout.write(_("%s not deleted! \n Error: %s")%(label,info)) + except Exception as info: + info = str(info) + sys.stdout.write(_("%s not deleted! \n Error: %s")%(label,info)) - dial.Destroy() + dial.Destroy() - else: - self.RemoveItem(item) + else: + self.RemoveItem(item) - ###TODO unload associated module + ###TODO unload associated module - else: - wx.MessageBox(_("No library selected!"),_("Delete Manager")) + else: + wx.MessageBox(_("No library selected!"),_("Delete Manager")) def UpdateSubLib(self, path:str)->bool: """ Do update lib. diff --git a/PreferencesGUI.py b/PreferencesGUI.py index 0a63929a..ec921991 100644 --- a/PreferencesGUI.py +++ b/PreferencesGUI.py @@ -136,12 +136,12 @@ def __init__(self, parent): (self.st4, 0, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, 5), (self.cb2, 0, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, 5)]) - vsizer.Add(self.plugin_dir, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND) - vsizer.Add(self.domain_dir, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND) - vsizer.Add(self.out_dir, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND) - vsizer.Add(hsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND) - vsizer.Add(self.cb1, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND) - vsizer.Add(self.cb11, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND) + vsizer.Add(self.plugin_dir, 1, wx.EXPAND) + vsizer.Add(self.domain_dir, 1, wx.EXPAND) + vsizer.Add(self.out_dir, 1, wx.EXPAND) + vsizer.Add(hsizer, 0, wx.EXPAND) + vsizer.Add(self.cb1, 1, wx.EXPAND) + vsizer.Add(self.cb11, 1, wx.EXPAND) box1.Add(vsizer, 1, wx.EXPAND) ### Set sizer @@ -335,29 +335,29 @@ def __init__(self, parent): ### Adding sizer hbox1.Add(self.cb1, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 15) - hbox1.Add(self.sim_success_sound_btn, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND|wx.ALL, 15) - hbox1.Add(self.sim_error_sound_btn, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND|wx.ALL, 15) + hbox1.Add(self.sim_success_sound_btn, 1, wx.EXPAND|wx.ALL, 15) + hbox1.Add(self.sim_error_sound_btn, 1, wx.EXPAND|wx.ALL, 15) - hbox5.Add(self.txt3, 0, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND|wx.ALL, 15) - hbox5.Add(self.cb3, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND|wx.ALL, 15) + hbox5.Add(self.txt3, 0, wx.EXPAND|wx.ALL, 15) + hbox5.Add(self.cb3, 1, wx.EXPAND|wx.ALL, 15) hbox5.Add(self.devs_doc_btn, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL) - hbox2.Add(self.txt, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL|wx.EXPAND, 15) - hbox2.Add(self.cb4, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER_HORIZONTAL|wx.ALL|wx.EXPAND, 15) + hbox2.Add(self.txt, 0, wx.ALL|wx.EXPAND, 15) + hbox2.Add(self.cb4, 1, wx.ALL|wx.EXPAND, 15) hbox3.Add(self.cb2, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 15) - hbox4.Add(self.txt2, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT|wx.ALL, 15) - hbox4.Add(self.sc, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT|wx.ALL, 15) + hbox4.Add(self.txt2, 0, wx.ALL, 15) + hbox4.Add(self.sc, 1, wx.ALL, 15) #hbox4.Add(information, 1, wx.ALIGN_CENTER_VERTICAL, 15) ##hbox4.Add(self.strategy_info, 1, wx.ALIGN_CENTER_VERTICAL, 15) - vbox.Add(hbox1, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.EXPAND|wx.ALL, 10) - vbox.Add(hbox5, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.EXPAND|wx.ALL, 10) - vbox.Add(hbox2, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.EXPAND|wx.ALL, 10) - vbox.Add(hbox3, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 10) - vbox.Add(hbox4, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 10) + vbox.Add(hbox1, 0, wx.EXPAND|wx.ALL, 10) + vbox.Add(hbox5, 0, wx.EXPAND|wx.ALL, 10) + vbox.Add(hbox2, 0, wx.EXPAND|wx.ALL, 10) + vbox.Add(hbox3, 0, wx.EXPAND|wx.ALL, 10) + vbox.Add(hbox4, 0, wx.EXPAND|wx.ALL, 10) ### Set sizer self.SetSizer(vbox) @@ -728,10 +728,10 @@ def __init__(self, parent, title): vsizer = wx.BoxSizer(wx.VERTICAL) hsizer = wx.BoxSizer(wx.HORIZONTAL) - hsizer.Add(self.cancel,0) + hsizer.Add(self.cancel,0,) hsizer.Add(self.apply,0, wx.EXPAND|wx.LEFT, 5) vsizer.Add(self.pref, 1, wx.ALL|wx.EXPAND, 5) - vsizer.Add(hsizer, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) + vsizer.Add(hsizer, 0, wx.RIGHT|wx.ALL, 5) panel.SetSizer(vsizer) vsizer.Fit(panel) diff --git a/PropPanel.py b/PropPanel.py index fc93ec53..8e7d8db3 100644 --- a/PropPanel.py +++ b/PropPanel.py @@ -33,7 +33,7 @@ def __init__(self, parent, name): self.frame = parent propSizer = wx.BoxSizer(wx.VERTICAL) - propSizer.Add(self.defaultPropertiesPage(), 1, wx.EXPAND|wx.ALL|wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTRE_VERTICAL, 10) + propSizer.Add(self.defaultPropertiesPage(), 1, wx.EXPAND|wx.ALL, 10) self.SetAutoLayout(True) self.SetSizerAndFit(propSizer) @@ -63,7 +63,7 @@ def UpdatePropertiesPage(self, panel=None): else: sizer.Clear(True) - sizer.Add(panel, 1, wx.EXPAND|wx.ALL|wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTRE_VERTICAL, 10) + sizer.Add(panel, 1, wx.EXPAND|wx.ALL, 10) self.SetSizerAndFit(sizer) self.Layout() diff --git a/SimulationGUI.py b/SimulationGUI.py index 4119caf7..c893c790 100644 --- a/SimulationGUI.py +++ b/SimulationGUI.py @@ -204,18 +204,18 @@ def MakePaneContent(self, pane): self.cb2.SetToolTipString(_("No time limit for the simulation. Simulation is over when childs are no active.")) grid3 = wx.GridSizer(6, 2, 1, 1) - grid3.Add(text2, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL, 19) - grid3.Add(ch1, 1, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL) - grid3.Add(text3, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL, 19) - grid3.Add(cb1, 1, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 19) - grid3.Add(text4, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL, 19) - grid3.Add(self.cb2, 1, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 19) - grid3.Add(text5, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL, 19) - grid3.Add(self.cb3, 1, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 19) - grid3.Add(text6, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL, 19) - grid3.Add(cb4, 1, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 19) - grid3.Add(text7, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL, 19) - grid3.Add(cb5, 1, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 19) + grid3.Add(text2, 0, wx.ALIGN_CENTER_VERTICAL, 19) + grid3.Add(ch1, 1, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL) + grid3.Add(text3, 0, wx.ALIGN_CENTER_VERTICAL, 19) + grid3.Add(cb1, 1, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 19) + grid3.Add(text4, 0, wx.ALIGN_CENTER_VERTICAL, 19) + grid3.Add(self.cb2, 1, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 19) + grid3.Add(text5, 0, wx.ALIGN_CENTER_VERTICAL, 19) + grid3.Add(self.cb3, 1, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 19) + grid3.Add(text6, 0, wx.ALIGN_CENTER_VERTICAL, 19) + grid3.Add(cb4, 1, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 19) + grid3.Add(text7, 0, wx.ALIGN_CENTER_VERTICAL, 19) + grid3.Add(cb5, 1, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 19) pane.SetSizer(grid3) @@ -367,10 +367,10 @@ def __do_layout(self): # panel2 grid2 = wx.GridSizer(3, 2, 2, 2) - grid2.Add(self._btn1, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER_HORIZONTAL|wx.EXPAND) - grid2.Add(self._btn3, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER_HORIZONTAL|wx.EXPAND) - grid2.Add(self._btn2, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER_HORIZONTAL|wx.EXPAND) - grid2.Add(self._btn4, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER_HORIZONTAL|wx.EXPAND) + grid2.Add(self._btn1, 0, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND) + grid2.Add(self._btn3, 0, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND) + grid2.Add(self._btn2, 0, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND) + grid2.Add(self._btn4, 0, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND) vbox_body.Add(grid1, 0, wx.EXPAND|wx.TOP, 9) vbox_body.Add((-1, 10)) diff --git a/devsimpy.py b/devsimpy.py index f7fb17c7..4acaa3d3 100644 --- a/devsimpy.py +++ b/devsimpy.py @@ -80,6 +80,15 @@ import wx +### try to have the latest version of wx +#try: +# import pip + #print(pip.main(['show','wxPython'])) + #pip.main(["install", "--upgrade", 'wxPython']) +#except: +# pass + +### check if an upgrade of wxpython is possible from pip ! sys.stdout.write("Importing wxPython %s%s for python %s on %s (%s) platform...\n"%(wx.version(), " from devsimpy.ini" if ini_exist else '', platform.python_version(), platform.system(), platform.version())) _ = wx.GetTranslation @@ -142,6 +151,7 @@ 'DEFAULT_SIM_STRATEGY': 'bag-based', #choose the default simulation strategy for PyDEVS 'PYDEVS_SIM_STRATEGY_DICT' : {'original':'SimStrategy1', 'bag-based':'SimStrategy2', 'direct-coupling':'SimStrategy3'}, # list of available simulation strategy for PyDEVS package 'PYPDEVS_SIM_STRATEGY_DICT' : {'classic':'SimStrategy4', 'distributed':'SimStrategy5', 'parallel':'SimStrategy6'}, # list of available simulation strategy for PyPDEVS package + 'PYPDEVS_221_SIM_STRATEGY_DICT' : {'classic':'SimStrategy4', 'distributed':'SimStrategy5', 'parallel':'SimStrategy6'}, # list of available simulation strategy for PyPDEVS package 'HELP_PATH' : os.path.join('doc', 'html'), # path of help directory 'NTL' : False, # No Time Limit for the simulation 'DYNAMIC_STRUCTURE' : False, # Dynamic Structure for local PyPDEVS simulation diff --git a/requirements.txt b/requirements.txt index ccc4c218..caede6af 100644 --- a/requirements.txt +++ b/requirements.txt @@ -51,7 +51,7 @@ # plugins\verbose.py: 14 # searchTreeList.py: 1 # wxPyMail.py: 22 -wxPython >= 4.0.6 +wxPython < 4.1.0 # Components.py: 44 # Container.py: 39 From 9d243633d985a61042d22163e89b0d28febab941 Mon Sep 17 00:00:00 2001 From: Capocchi L Date: Fri, 29 May 2020 23:06:00 +0200 Subject: [PATCH 3/3] bug fixes and improvements toward wx 4.1.0 --- Components.py | 2 +- ImportLibrary.py | 24 ++++++++++++++++++++---- PluginsGUI.py | 2 +- PreferencesGUI.py | 7 ++++--- ZipManager.py | 42 +++++++++++++++++++++++++++++++++--------- devsimpy.py | 2 +- 6 files changed, 60 insertions(+), 19 deletions(-) diff --git a/Components.py b/Components.py index 1cf51fda..72f16f96 100644 --- a/Components.py +++ b/Components.py @@ -49,7 +49,7 @@ import ZipManager from ReloadModule import recompile -from Utilities import GetActiveWindow, path_to_module, install_and_import, printOnStatusBar +from Utilities import GetActiveWindow, path_to_module, printOnStatusBar from NetManager import Net from SimpleFrameEditor import FrameEditor from which import which diff --git a/ImportLibrary.py b/ImportLibrary.py index 42a29316..8919ca5c 100644 --- a/ImportLibrary.py +++ b/ImportLibrary.py @@ -39,10 +39,15 @@ from Decorators import BuzyCursorNotification class CheckListCtrl(wx.ListCtrl, CheckListCtrlMixin, ListCtrlAutoWidthMixin): - def __init__(self, parent): - wx.ListCtrl.__init__(self, parent, wx.NewIdRef(), style=wx.LC_REPORT | wx.SUNKEN_BORDER|wx.LC_SORT_ASCENDING) - CheckListCtrlMixin.__init__(self) + def __init__(self, *args, **kw): + wx.ListCtrl.__init__(self, *args, **kw) ListCtrlAutoWidthMixin.__init__(self) + + if wx.VERSION_STRING >= '4.1.0': + self.EnableCheckBoxes(True) + self.IsChecked = self.IsItemChecked + else: + CheckListCtrlMixin.__init__(self) self.InsertColumn(0, _('Name'), width=140) self.InsertColumn(1, _('Size [Ko]'), width=80) @@ -63,6 +68,17 @@ def __init__(self, parent): self.SetFont(font) + # self.Bind(wx.EVT_LIST_ITEM_CHECKED, self.OnCheck) + # self.Bind(wx.EVT_LIST_ITEM_UNCHECKED, self.OnUnCheck) + + # def OnCheck(self, evt): + # index = evt.GetItem().GetId() + # self.CheckItem(index, True) + + # def OnUnCheck(self, evt): + # index = evt.GetItem().GetId() + # self.CheckItem(index, False) + def AddItem(self, path, dName, check=False): """ Add item to the list """ @@ -206,7 +222,7 @@ def __init__(self, *args, **kwargs): rightPanel = wx.Panel(panel, wx.NewIdRef()) ### Check list of libraries - self._cb = CheckListCtrl(rightPanel) + self._cb = CheckListCtrl(parent=rightPanel, style=wx.LC_REPORT | wx.SUNKEN_BORDER|wx.LC_SORT_ASCENDING) try: if wx.Platform == '__WXMSW__': diff --git a/PluginsGUI.py b/PluginsGUI.py index 7587660f..405ace10 100644 --- a/PluginsGUI.py +++ b/PluginsGUI.py @@ -619,7 +619,7 @@ def __init__(self, parent): self.log.SetToolTipString(_("Plug-in documentation area.\nSelect plug-in in order to print its documentation.")) ### Default plug-ins list - self.check_list = CheckListCtrl(self.rightPanel) + self.check_list = CheckListCtrl(parent=self.rightPanel, style=wx.LC_REPORT | wx.SUNKEN_BORDER|wx.LC_SORT_ASCENDING) ### Buttons selBtn = wx.Button(self.leftPanel, wx.ID_SELECTALL, size=(140, -1)) diff --git a/PreferencesGUI.py b/PreferencesGUI.py index ec921991..87635530 100644 --- a/PreferencesGUI.py +++ b/PreferencesGUI.py @@ -37,6 +37,7 @@ if __name__ == '__main__': builtins.__dict__['HOME_PATH'] = os.getcwd() + builtins.__dict__['NOTIFICATION'] = False builtins.__dict__['DEFAULT_DEVS_DIRNAME'] = 'PyDEVS' builtins.__dict__['DEVS_DIR_PATH_DICT'] = {'PyDEVS':os.path.join(HOME_PATH,'DEVSKernel','PyDEVS'), 'PyPDEVS_221':os.path.join(HOME_PATH,'DEVSKernel','PyPDEVS','pypdevs221' ,'src'), @@ -728,10 +729,10 @@ def __init__(self, parent, title): vsizer = wx.BoxSizer(wx.VERTICAL) hsizer = wx.BoxSizer(wx.HORIZONTAL) - hsizer.Add(self.cancel,0,) - hsizer.Add(self.apply,0, wx.EXPAND|wx.LEFT, 5) + hsizer.Add(self.cancel, 0) + hsizer.Add(self.apply, 0, wx.EXPAND|wx.LEFT, 5) vsizer.Add(self.pref, 1, wx.ALL|wx.EXPAND, 5) - vsizer.Add(hsizer, 0, wx.RIGHT|wx.ALL, 5) + vsizer.Add(hsizer, 0, wx.ALL|wx.ALIGN_RIGHT, 5) panel.SetSizer(vsizer) vsizer.Fit(panel) diff --git a/ZipManager.py b/ZipManager.py index 4b18d1b1..ac5a7882 100644 --- a/ZipManager.py +++ b/ZipManager.py @@ -26,7 +26,7 @@ from PluginManager import PluginManager #trigger_event from traceback import format_exception -from Utilities import listf, path_to_module +from Utilities import listf, path_to_module,install_and_import #global Cmtp #Cmtp=0 @@ -323,16 +323,40 @@ def ImportModule(self)->types.ModuleType: sys.path.append(p) importer = zipimport.zipimporter(self.fn) - module = importer.load_module(self.module_name.split('.py')[0]) - module.__name__ = path_to_module(self.module_name) - ### allows to import with a reference from the parent directory (like parentName.model). - ### Now import of .amd or .cmd module is composed by DomainModel (no point!). - ### Example : import CollectorMessageCollector - sys.modules[self.fullname] = module + try: + module = importer.load_module(self.module_name.split('.py')[0]) + + ### package is needed by the self.module_name (dependency) + except ModuleNotFoundError as info: + ### get the package name + package = sys.exc_info()[1].name + + import wx + dial = wx.MessageDialog(None, _('%s package is needed by %s.\nDo you want to install it?')%(package,self.module_name), _('Required package'), wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION) + if dial.ShowModal() == wx.ID_YES: + ### try to install + if install_and_import(package): + module = importer.load_module(self.module_name.split('.py')[0]) + else: + module = None + else: + module = None + + dial.Destroy() + finally: + if module: + module.__name__ = path_to_module(self.module_name) + + ### allows to import with a reference from the parent directory (like parentName.model). + ### Now import of .amd or .cmd module is composed by DomainModel (no point!). + ### Example : import CollectorMessageCollector + sys.modules[self.fullname] = module + + return module + else: + return None - return module - def ReImport(self): """ Reimport the module from zip file. """ diff --git a/devsimpy.py b/devsimpy.py index 4acaa3d3..5abece6d 100644 --- a/devsimpy.py +++ b/devsimpy.py @@ -1482,7 +1482,7 @@ def OnImport(self, event): num = dlg._cb.GetItemCount() for index in range(num): label = dlg._cb.GetItemText(index) - + ### met a jour le dico des elements selectionnes if dlg._cb.IsChecked(index) and label not in dlg._selectedItem: dlg._selectedItem.update({str(label):index})