PaIRS-UniNa 0.2.4__cp311-cp311-win_amd64.whl → 0.2.6__cp311-cp311-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of PaIRS-UniNa might be problematic. Click here for more details.
- PaIRS_UniNa/Changes.txt +35 -0
- PaIRS_UniNa/Custom_Top.py +1 -1
- PaIRS_UniNa/Explorer.py +3063 -3049
- PaIRS_UniNa/FolderLoop.py +371 -371
- PaIRS_UniNa/Input_Tab.py +717 -709
- PaIRS_UniNa/Input_Tab_CalVi.py +4 -4
- PaIRS_UniNa/Input_Tab_tools.py +3018 -3009
- PaIRS_UniNa/Output_Tab.py +2 -2
- PaIRS_UniNa/PaIRS.py +17 -17
- PaIRS_UniNa/PaIRS_PIV.py +56 -1
- PaIRS_UniNa/PaIRS_pypacks.py +323 -60
- PaIRS_UniNa/Process_Tab.py +8 -13
- PaIRS_UniNa/Process_Tab_Disp.py +9 -4
- PaIRS_UniNa/Saving_tools.py +277 -277
- PaIRS_UniNa/TabTools.py +63 -21
- PaIRS_UniNa/Vis_Tab.py +293 -115
- PaIRS_UniNa/Whatsnew.py +13 -0
- PaIRS_UniNa/_PaIRS_PIV.pyd +0 -0
- PaIRS_UniNa/__init__.py +3 -3
- PaIRS_UniNa/gPaIRS.py +3825 -3600
- PaIRS_UniNa/icons/flaticon_PaIRS_download_warning.png +0 -0
- PaIRS_UniNa/icons/pencil_bw.png +0 -0
- PaIRS_UniNa/icons/pylog.png +0 -0
- PaIRS_UniNa/icons/python_warning.png +0 -0
- PaIRS_UniNa/icons/queue.png +0 -0
- PaIRS_UniNa/icons/uninitialized.png +0 -0
- PaIRS_UniNa/icons/window.png +0 -0
- PaIRS_UniNa/listLib.py +301 -301
- PaIRS_UniNa/parForMulti.py +433 -433
- PaIRS_UniNa/parForWorkers.py +46 -1
- PaIRS_UniNa/pivParFor.py +1 -1
- PaIRS_UniNa/procTools.py +17 -7
- PaIRS_UniNa/rqrdpckgs.txt +9 -0
- PaIRS_UniNa/stereoPivParFor.py +1 -1
- PaIRS_UniNa/tabSplitter.py +606 -606
- PaIRS_UniNa/ui_Calibration_Tab.py +542 -542
- PaIRS_UniNa/ui_Custom_Top.py +294 -294
- PaIRS_UniNa/ui_Input_Tab.py +1098 -1098
- PaIRS_UniNa/ui_Input_Tab_CalVi.py +1280 -1280
- PaIRS_UniNa/ui_Log_Tab.py +261 -261
- PaIRS_UniNa/ui_Output_Tab.py +2360 -2360
- PaIRS_UniNa/ui_Process_Tab.py +3808 -3808
- PaIRS_UniNa/ui_Process_Tab_CalVi.py +1547 -1547
- PaIRS_UniNa/ui_Process_Tab_Disp.py +1139 -968
- PaIRS_UniNa/ui_Process_Tab_Min.py +435 -435
- PaIRS_UniNa/ui_ResizePopup.py +203 -203
- PaIRS_UniNa/ui_Vis_Tab.py +1626 -1533
- PaIRS_UniNa/ui_Vis_Tab_CalVi.py +1249 -1249
- PaIRS_UniNa/ui_Whatsnew.py +131 -131
- PaIRS_UniNa/ui_gPairs.py +873 -849
- PaIRS_UniNa/ui_infoPaIRS.py +550 -428
- PaIRS_UniNa/whatsnew.txt +4 -4
- {PaIRS_UniNa-0.2.4.dist-info → pairs_unina-0.2.6.dist-info}/METADATA +47 -30
- {PaIRS_UniNa-0.2.4.dist-info → pairs_unina-0.2.6.dist-info}/RECORD +56 -51
- {PaIRS_UniNa-0.2.4.dist-info → pairs_unina-0.2.6.dist-info}/WHEEL +1 -1
- PaIRS_UniNa/stereo.py +0 -685
- PaIRS_UniNa-0.2.4.dist-info/LICENSE +0 -19
- {PaIRS_UniNa-0.2.4.dist-info → pairs_unina-0.2.6.dist-info}/top_level.txt +0 -0
PaIRS_UniNa/PaIRS_pypacks.py
CHANGED
|
@@ -15,11 +15,14 @@ basefold_DEBUG='./'
|
|
|
15
15
|
basefold_DEBUG_VIS=''
|
|
16
16
|
#basefold='B:/dl/apairs/jetcross'
|
|
17
17
|
|
|
18
|
+
|
|
18
19
|
developerIDs={
|
|
19
20
|
'GP_Win_Office': '231128824800632', #'0x7824af430781',
|
|
20
21
|
'GP_Win_Office_New': '140626882900161', #'0x7824af430781',
|
|
21
22
|
'GP_Mac_Laptop': 'V94LRP93FV', #'0xa275dd445ab0',
|
|
23
|
+
'GP_WSL' : 'b44ec1c0e5a74ffd97bb050c39ef6cb1',
|
|
22
24
|
'TA_Win_Office': '160983906000941', #'0xccb0da8c896e'
|
|
25
|
+
'TA_Win_Office_New': '231128824801036', #??
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
import psutil,subprocess
|
|
@@ -28,9 +31,32 @@ def getCurrentID():
|
|
|
28
31
|
serial_number=None
|
|
29
32
|
try:
|
|
30
33
|
if psutil.LINUX:
|
|
34
|
+
def get_linux_serial():
|
|
35
|
+
from pathlib import Path
|
|
36
|
+
candidates = [
|
|
37
|
+
Path("/sys/class/dmi/id/board_serial"),
|
|
38
|
+
Path("/sys/class/dmi/id/product_uuid"),
|
|
39
|
+
Path("/etc/machine-id"), Path("/var/lib/dbus/machine-id") #WSL
|
|
40
|
+
]
|
|
41
|
+
for p in candidates:
|
|
42
|
+
try:
|
|
43
|
+
if p.is_file():
|
|
44
|
+
val = p.read_text(errors="ignore").strip()
|
|
45
|
+
if val and val.lower() not in {
|
|
46
|
+
"none", "unknown", "not specified", "to be filled by o.e.m."
|
|
47
|
+
}:
|
|
48
|
+
return val
|
|
49
|
+
except Exception as e:
|
|
50
|
+
if Flag_DEBUG:
|
|
51
|
+
print(f"Error while retrieving motherboard serial number: {e}")
|
|
52
|
+
continue
|
|
53
|
+
return None
|
|
54
|
+
serial_number = get_linux_serial()
|
|
55
|
+
""""
|
|
31
56
|
# On Linux, the motherboard serial number can be obtained from the /sys/class/dmi/id/board_serial file
|
|
32
57
|
with open('/sys/class/dmi/id/board_serial', 'r') as f:
|
|
33
58
|
serial_number = f.read().strip()
|
|
59
|
+
"""
|
|
34
60
|
elif psutil.WINDOWS:
|
|
35
61
|
# On Windows, the motherboard serial number can be obtained using WMI
|
|
36
62
|
output = subprocess.check_output(["wmic", "baseboard", "get", "SerialNumber"]).decode('utf-8')
|
|
@@ -42,7 +68,8 @@ def getCurrentID():
|
|
|
42
68
|
if b'Serial Number (system)' in line:
|
|
43
69
|
serial_number = line.split(b':')[1].strip().decode('utf-8')
|
|
44
70
|
except Exception as e:
|
|
45
|
-
|
|
71
|
+
if Flag_DEBUG:
|
|
72
|
+
print(f"Error while retrieving motherboard serial number: {e}")
|
|
46
73
|
return serial_number
|
|
47
74
|
|
|
48
75
|
currentID=getCurrentID()
|
|
@@ -57,6 +84,16 @@ if currentID in (developerIDs['GP_Win_Office'],developerIDs['GP_Win_Office_New']
|
|
|
57
84
|
'C:/desk/PIV_Img/_data/Calibration_data/cylinder/',
|
|
58
85
|
]
|
|
59
86
|
basefold_DEBUG_VIS='C:/desk/PIV_Img/_data/PIV_data/real_case/'
|
|
87
|
+
elif currentID==developerIDs['GP_WSL']:
|
|
88
|
+
basefold_DEBUG='/mnt/c/desk/PIV_Img/_data/PIV_data/virtual_case/'
|
|
89
|
+
basefold_DEBUGOptions=[
|
|
90
|
+
'/mnt/c/desk/PIV_Img/img1/',
|
|
91
|
+
'/mnt/c/desk/PIV_Img/_data/PIV_data/virtual_case/',
|
|
92
|
+
'/mnt/c/desk/PIV_Img/_data/PIV_data/real_case/',
|
|
93
|
+
'/mnt/c/desk/PIV_Img/_data/Calibration_data/pinhole/',
|
|
94
|
+
'/mnt/c/desk/PIV_Img/_data/Calibration_data/cylinder/',
|
|
95
|
+
]
|
|
96
|
+
basefold_DEBUG_VIS='/mnt/c/desk/PIV_Img/_data/PIV_data/real_case/'
|
|
60
97
|
elif currentID==developerIDs['GP_Mac_Laptop']: #gerardo mac
|
|
61
98
|
basefold_DEBUG='/Users/gerardo/Desktop/PIV_Img/swirler_png/' #'/Users/gerardo/Desktop/PIV_Img/img1/'
|
|
62
99
|
basefold_DEBUGOptions=[
|
|
@@ -64,18 +101,19 @@ elif currentID==developerIDs['GP_Mac_Laptop']: #gerardo mac
|
|
|
64
101
|
'/Users/gerardo/Desktop/PaIRS_examples/PIV_data/virtual_case/',
|
|
65
102
|
#'/Users/gerardo/Desktop/PaIRS_examples/PIV_data/virtual_case_2/',
|
|
66
103
|
'/Users/gerardo/Desktop/PaIRS_examples/PIV_data/real_case/',
|
|
104
|
+
'/Users/gerardo/Desktop/PaIRS_examples/SPIV_data/real_case/img/',
|
|
67
105
|
'/Users/gerardo/Desktop/PaIRS_examples/Calibration_data/pinhole/',
|
|
68
106
|
'/Users/gerardo/Desktop/PaIRS_examples/Calibration_data/cylinder/'
|
|
69
107
|
]
|
|
70
108
|
basefold_DEBUG_VIS='/Users/gerardo/Desktop/PaIRS_examples/PIV_data/real_case/'
|
|
71
109
|
basefold_DEBUG_VIS='/Users/gerardo/Desktop/PIV_Img/img1/'
|
|
72
|
-
elif currentID
|
|
73
|
-
basefold_DEBUG='C:\desk\Attuali\PythonLibC\PIV\img'
|
|
110
|
+
elif currentID in (developerIDs['TA_Win_Office'],developerIDs['TA_Win_Office_New']): #TA windows
|
|
111
|
+
basefold_DEBUG=r'C:\desk\Attuali\PythonLibC\PIV\img'
|
|
74
112
|
basefold_DEBUGOptions=[
|
|
75
113
|
'C:/desk/PIV_Img/img1/',
|
|
76
114
|
'C:/desk/PIV_Img/swirler_png/',
|
|
77
115
|
'../../img/calib/',
|
|
78
|
-
'C:\desk\Attuali\PythonLibC\PIV\img',
|
|
116
|
+
r'C:\desk\Attuali\PythonLibC\PIV\img',
|
|
79
117
|
]
|
|
80
118
|
basefold_DEBUG_VIS=''
|
|
81
119
|
else:
|
|
@@ -147,6 +185,37 @@ import sys
|
|
|
147
185
|
import concurrent.futures
|
|
148
186
|
import asyncio
|
|
149
187
|
|
|
188
|
+
_old_init_QAction = QAction.__init__
|
|
189
|
+
def _new_init_QAction(self, *args, **kwargs):
|
|
190
|
+
_old_init_QAction(self, *args, **kwargs)
|
|
191
|
+
try:
|
|
192
|
+
self.setIconVisibleInMenu(True)
|
|
193
|
+
except Exception:
|
|
194
|
+
pass
|
|
195
|
+
QAction.__init__ = _new_init_QAction
|
|
196
|
+
_old_init_QMenu = QMenu.__init__
|
|
197
|
+
def _new_init_QMenu(self, *args, **kwargs):
|
|
198
|
+
_old_init_QMenu(self, *args, **kwargs)
|
|
199
|
+
try:
|
|
200
|
+
self.menuAction().setIconVisibleInMenu(True)
|
|
201
|
+
except Exception:
|
|
202
|
+
pass
|
|
203
|
+
QMenu.__init__ = _new_init_QMenu
|
|
204
|
+
|
|
205
|
+
# --- Patch dei metodi QMenu che CREANO/AGGIUNGONO azioni (copre gli overload C++) ---
|
|
206
|
+
_old_addAction = QMenu.addAction
|
|
207
|
+
def _new_addAction(self, *args, **kwargs):
|
|
208
|
+
act:QAction = _old_addAction(self, *args, **kwargs) # può essere creato lato C++
|
|
209
|
+
try:
|
|
210
|
+
if isinstance(act, QAction):
|
|
211
|
+
act.setIconVisibleInMenu(True)
|
|
212
|
+
except Exception:
|
|
213
|
+
pass
|
|
214
|
+
return act
|
|
215
|
+
QMenu.addAction = _new_addAction
|
|
216
|
+
|
|
217
|
+
Flag_ISEXE=getattr(sys, 'frozen', False) #made by pyInstaller
|
|
218
|
+
EXEurl='https://www.pairs.unina.it/#download'
|
|
150
219
|
|
|
151
220
|
class ColorPrint:
|
|
152
221
|
def __init__(self,flagTime=False,prio=PrintTAPriority.medium,faceStd=PrintTA.faceStd,flagFullDebug=False):
|
|
@@ -182,6 +251,7 @@ class GPaIRSPrint:
|
|
|
182
251
|
self.Info=ColorPrint(prio=PrintTAPriority.medium)
|
|
183
252
|
self.Time=ColorPrint(prio=PrintTAPriority.medium if FlagPrintTime else PrintTAPriority.veryLow,flagTime=True,faceStd=PrintTA.faceUnderline)
|
|
184
253
|
self.Error=ColorPrint(prio=PrintTAPriority.medium,faceStd=PrintTA.faceBold)
|
|
254
|
+
self.IOError=ColorPrint(prio=PrintTAPriority.veryLow,faceStd=PrintTA.faceBold)
|
|
185
255
|
self.Process=ColorPrint(prio=PrintTAPriority.veryLow)
|
|
186
256
|
self.Callback=ColorPrint(prio=PrintTAPriority.veryLow)
|
|
187
257
|
self.TABparDiff=ColorPrint(prio=PrintTAPriority.veryLow)
|
|
@@ -235,7 +305,6 @@ if __package__ or "." in __name__:
|
|
|
235
305
|
foldPaIRS = foldPaIRS.replace('\\', '/')
|
|
236
306
|
else:
|
|
237
307
|
foldPaIRS='./'
|
|
238
|
-
|
|
239
308
|
class ProcessTypes:
|
|
240
309
|
null=None
|
|
241
310
|
min=0
|
|
@@ -245,7 +314,7 @@ class ProcessTypes:
|
|
|
245
314
|
cal=10
|
|
246
315
|
|
|
247
316
|
singleCamera=[piv]
|
|
248
|
-
threeCameras=[tpiv]
|
|
317
|
+
threeCameras=[min,tpiv]
|
|
249
318
|
|
|
250
319
|
class StepTypes:
|
|
251
320
|
null=None
|
|
@@ -289,15 +358,24 @@ class outExt:
|
|
|
289
358
|
cfg_calvi='.calvi_cfg'
|
|
290
359
|
pla='.pairs_pla'
|
|
291
360
|
|
|
292
|
-
|
|
293
361
|
|
|
294
362
|
lastcfgname='lastWorkSpace'+outExt.wksp
|
|
295
|
-
|
|
296
363
|
fileChanges=foldPaIRS+'Changes.txt'
|
|
297
|
-
fileWhatsNew=[foldPaIRS+f for f in fileWhatsNew]
|
|
298
364
|
icons_path=foldPaIRS+icons_path
|
|
299
|
-
|
|
300
|
-
|
|
365
|
+
|
|
366
|
+
if not Flag_ISEXE:
|
|
367
|
+
fileWhatsNew=[foldPaIRS+f for f in fileWhatsNew]
|
|
368
|
+
|
|
369
|
+
lastcfgname=foldPaIRS+lastcfgname
|
|
370
|
+
pro_path=foldPaIRS+"pro/"
|
|
371
|
+
else:
|
|
372
|
+
from pathlib import Path
|
|
373
|
+
exe_dir = str(Path(sys.argv[0]).resolve().parent)+'/'
|
|
374
|
+
fileWhatsNew=[foldPaIRS+fileWhatsNew[0],exe_dir+fileWhatsNew[1]]
|
|
375
|
+
lastcfgname = exe_dir + lastcfgname
|
|
376
|
+
pro_path = exe_dir + "pro/"
|
|
377
|
+
|
|
378
|
+
|
|
301
379
|
if not os.path.exists(pro_path):
|
|
302
380
|
try:
|
|
303
381
|
os.mkdir(pro_path)
|
|
@@ -319,7 +397,7 @@ if Flag_NATIVEDIALOGS:
|
|
|
319
397
|
else:
|
|
320
398
|
optionNativeDialog=QFileDialog.Option.DontUseNativeDialog
|
|
321
399
|
|
|
322
|
-
def warningDialog(self:QWidget,Message,time_milliseconds=0,flagScreenCenter=False,icon:QIcon=QIcon(),palette=None,pixmap=None,title='Warning!',flagRichText=False,flagNoButtons=False,addButton:dict=None,FlagStayOnTop=False): #addButton=['Print Message',lambda: print(Message)]
|
|
400
|
+
def warningDialog(self:QWidget,Message,time_milliseconds=0,flagScreenCenter=False,icon:QIcon=QIcon(),palette=None,pixmap=None,title='Warning!',flagRichText=False,flagNoButtons=False,addButton:dict=None,FlagStayOnTop=False,pixmapSize=64): #addButton=['Print Message',lambda: print(Message)]
|
|
323
401
|
dlg=None
|
|
324
402
|
if Message:
|
|
325
403
|
if isinstance(self,QMainWindow) and hasattr(self,'w_Input'):
|
|
@@ -328,6 +406,7 @@ def warningDialog(self:QWidget,Message,time_milliseconds=0,flagScreenCenter=Fals
|
|
|
328
406
|
dlg = QMessageBox(self)
|
|
329
407
|
dlg.setWindowTitle(title)
|
|
330
408
|
dlg.setText(str(Message))
|
|
409
|
+
|
|
331
410
|
if flagRichText: dlg.setTextFormat(Qt.TextFormat.RichText)
|
|
332
411
|
if flagNoButtons:
|
|
333
412
|
dlg.setStandardButtons(QMessageBox.StandardButton.NoButton)
|
|
@@ -361,7 +440,7 @@ def warningDialog(self:QWidget,Message,time_milliseconds=0,flagScreenCenter=Fals
|
|
|
361
440
|
if palette:
|
|
362
441
|
dlg.setPalette(palette)
|
|
363
442
|
if pixmap:
|
|
364
|
-
dlg.setIconPixmap(QPixmap(pixmap).scaled(
|
|
443
|
+
dlg.setIconPixmap(QPixmap(pixmap).scaled(pixmapSize, pixmapSize, Qt.AspectRatioMode.KeepAspectRatio,Qt.SmoothTransformation))
|
|
365
444
|
if self:
|
|
366
445
|
dlg.setFont(self.font())
|
|
367
446
|
c=dlg.findChildren(QObject)
|
|
@@ -685,10 +764,9 @@ def toPlainText(text):
|
|
|
685
764
|
return PlainTextConverter.toPlainText()
|
|
686
765
|
|
|
687
766
|
def showTip(obj,message):
|
|
688
|
-
tip=QToolTip(obj)
|
|
689
767
|
toolTipDuration=obj.toolTipDuration()
|
|
690
768
|
obj.setToolTipDuration(3000)
|
|
691
|
-
|
|
769
|
+
QToolTip.showText(QCursor.pos(),message)
|
|
692
770
|
obj.setToolTipDuration(toolTipDuration)
|
|
693
771
|
|
|
694
772
|
def clean_tree(tree:QTreeWidget):
|
|
@@ -780,12 +858,16 @@ def runPaIRS(self,command='',flagQuestion=True):
|
|
|
780
858
|
def run(self):
|
|
781
859
|
try:
|
|
782
860
|
import subprocess
|
|
783
|
-
if
|
|
784
|
-
pri.Info.white(sys.executable+'
|
|
785
|
-
subprocess.call(sys.executable+'
|
|
861
|
+
if Flag_ISEXE:
|
|
862
|
+
pri.Info.white(sys.executable+' '+command)
|
|
863
|
+
subprocess.call(sys.executable+' '+command,shell=True)
|
|
786
864
|
else:
|
|
787
|
-
|
|
788
|
-
|
|
865
|
+
if Flag: #launched from package
|
|
866
|
+
pri.Info.white(sys.executable+' -m PaIRS_UniNa '+command)
|
|
867
|
+
subprocess.call(sys.executable+' -m PaIRS_UniNa '+command,shell=True)
|
|
868
|
+
else:
|
|
869
|
+
pri.Info.white(sys.executable+' -c '+'"'+f"import os; os.chdir('{os.getcwd()}'); {pyCommands[command]}"+'"')
|
|
870
|
+
subprocess.call(sys.executable+' -c '+'"'+f"import os; os.chdir('{os.getcwd()}'); {pyCommands[command]}"+'"',shell=True)
|
|
789
871
|
self.isRunning=False
|
|
790
872
|
except Exception as inst:
|
|
791
873
|
pri.Error.red(inst)
|
|
@@ -814,12 +896,12 @@ def showSplash(filename=''+ icons_path +'logo_PaIRS_completo.png'):
|
|
|
814
896
|
splash.show()
|
|
815
897
|
return splash
|
|
816
898
|
|
|
817
|
-
def checkLatestVersion(self,version,app:QApplication=None,splash:QLabel=None):
|
|
899
|
+
def checkLatestVersion(self,version,app:QApplication=None,splash:QLabel=None,flagWarning=1):
|
|
818
900
|
flagStopAndDownload=False
|
|
819
901
|
var=self.TABpar
|
|
820
902
|
#var.FlagOutDated=0 if currentVersion==var.latestVersion else var.FlagOutDated
|
|
821
903
|
if abs(var.FlagOutDated)==1:
|
|
822
|
-
warningLatestVersion(self,app,flagExit=0,flagWarning=
|
|
904
|
+
warningLatestVersion(self,app,flagExit=0,flagWarning=flagWarning,FlagStayOnTop=True)
|
|
823
905
|
var.FlagOutDated=2 if var.FlagOutDated==1 else -2
|
|
824
906
|
"""
|
|
825
907
|
flagStopAndDownload=questionDialog(self,f'A new version of the PaIRS_UniNa package is available. Do you want to download it before starting the current istance of {self.name}?')
|
|
@@ -850,7 +932,7 @@ def checkLatestVersion(self,version,app:QApplication=None,splash:QLabel=None):
|
|
|
850
932
|
var.FlagOutDated=-2 if var.FlagOutDated==-2 else -1
|
|
851
933
|
elif flagOutDated==-1000:
|
|
852
934
|
sOut=f'Error from pip: it was not possible to check for a new version of the {packageName} package!'
|
|
853
|
-
var.FlagOutDated
|
|
935
|
+
var.FlagOutDated=-1000
|
|
854
936
|
else:
|
|
855
937
|
sOut=f'{packageName} The current version ({currentVersion}) of {packageName} is up-to-date! Enjoy it!'
|
|
856
938
|
var.FlagOutDated=0
|
|
@@ -870,13 +952,18 @@ def warningLatestVersion(self,app,flagExit=0,flagWarning=0,time_milliseconds=0,F
|
|
|
870
952
|
py=myStandardRoot(sys.executable).split('/')[-1].split('.')[0]
|
|
871
953
|
command=f'{py} -m pip install --upgrade PaIRS_UniNa'
|
|
872
954
|
if self.TABpar.FlagOutDated>0:
|
|
873
|
-
|
|
955
|
+
if Flag_ISEXE:
|
|
956
|
+
Message=f'A new version of the PaIRS_UniNa package is available (current: {self.TABpar.currentVersion}, latest: {self.TABpar.latestVersion}).\nPlease, download it from the following link:\n{EXEurl}'
|
|
957
|
+
else:
|
|
958
|
+
Message=f'A new version of the PaIRS_UniNa package is available (current: {self.TABpar.currentVersion}, latest: {self.TABpar.latestVersion}).\nPlease, {exitSuggestion}install it with the following command:\n{command}'
|
|
959
|
+
elif self.TABpar.FlagOutDated==-1000:
|
|
960
|
+
Message = ("Unable to check for the latest official release of PaIRS_UniNa. Please check the PyPI page manually for updates:\n""https://pypi.org/project/PaIRS-UniNa/")
|
|
874
961
|
else:
|
|
875
962
|
Message=f'The version of the current instance of PaIRS_UniNa ({self.TABpar.currentVersion}) is newer than the latest official releas ({self.TABpar.latestVersion})!\nYou should contact Tommaso and Gerardo if you are a developer and some relevant change is made by yourself!\nIf you are a user, enjoy this beta version and please report any issue!'
|
|
876
963
|
if flagExit:
|
|
877
964
|
print(f"\n{'*'*100}\n"+Message+f"\n{'*'*100}\n")
|
|
878
965
|
if flagWarning:
|
|
879
|
-
warningDialog(self,Message,time_milliseconds=time_milliseconds,flagScreenCenter=True,pixmap=''+ icons_path +'flaticon_PaIRS_download.png' if self.TABpar.FlagOutDated>0 else ''+ icons_path +'flaticon_PaIRS_beta.png',FlagStayOnTop=FlagStayOnTop,addButton={"See what's new!": lambda: QDesktopServices.openUrl(QUrl("https://pypi.org/project/PaIRS-UniNa/"))} if self.TABpar.FlagOutDated>0 else {})
|
|
966
|
+
warningDialog(self,Message,time_milliseconds=time_milliseconds,flagScreenCenter=True,pixmap=''+ icons_path +'flaticon_PaIRS_download.png' if self.TABpar.FlagOutDated>0 else ''+ icons_path +'flaticon_PaIRS_download_warning.png' if self.TABpar.FlagOutDated==-1000 else ''+ icons_path +'flaticon_PaIRS_beta.png',FlagStayOnTop=FlagStayOnTop,addButton={"Go to the download page!": lambda: QDesktopServices.openUrl(QUrl(EXEurl))} if Flag_ISEXE else {"See what's new!": lambda: QDesktopServices.openUrl(QUrl("https://pypi.org/project/PaIRS-UniNa/"))} if self.TABpar.FlagOutDated>0 else {})
|
|
880
967
|
|
|
881
968
|
def downloadLatestVersion(self,app):
|
|
882
969
|
try:
|
|
@@ -900,6 +987,7 @@ def downloadLatestVersion(self,app):
|
|
|
900
987
|
|
|
901
988
|
def button_download_PaIRS_action(self,app):
|
|
902
989
|
warningLatestVersion(self,app,flagExit=0,flagWarning=1)
|
|
990
|
+
checkLatestVersion(self,__version__,self.app,splash=None,flagWarning=0)
|
|
903
991
|
return
|
|
904
992
|
flagStopAndDownload=questionDialog(self,f'A new version of the PaIRS_UniNa package is available. Do you want to close the current instance of {self.name} and download it?')
|
|
905
993
|
if not flagStopAndDownload: return
|
|
@@ -911,6 +999,20 @@ def button_download_PaIRS_action(self,app):
|
|
|
911
999
|
else: command=''
|
|
912
1000
|
subprocess.call(sys.executable+' -m PaIRS_UniNa '+command,shell=True)
|
|
913
1001
|
#runPaIRS(self,flagQuestion=False)
|
|
1002
|
+
|
|
1003
|
+
import urllib.request, json, ssl
|
|
1004
|
+
|
|
1005
|
+
def get_package_version_urllib(package_name):
|
|
1006
|
+
"""Get package version using only standard library"""
|
|
1007
|
+
try:
|
|
1008
|
+
import certifi
|
|
1009
|
+
url = f"https://pypi.org/pypi/{package_name}/json"
|
|
1010
|
+
context = ssl.create_default_context(cafile=certifi.where())
|
|
1011
|
+
with urllib.request.urlopen(url, context=context, timeout=10) as response:
|
|
1012
|
+
data = json.loads(response.read().decode())
|
|
1013
|
+
return True, data['info']['version']
|
|
1014
|
+
except Exception as e:
|
|
1015
|
+
return False, f"Error: {e}"
|
|
914
1016
|
|
|
915
1017
|
def checkOutDated(packageName:str,printOutDated):
|
|
916
1018
|
'''
|
|
@@ -942,48 +1044,60 @@ def checkOutDated(packageName:str,printOutDated):
|
|
|
942
1044
|
currentVersion='none'
|
|
943
1045
|
latestVersion=''
|
|
944
1046
|
try:
|
|
945
|
-
if
|
|
1047
|
+
if Flag_ISEXE:
|
|
946
1048
|
currentVersion=__version__+'.'+__subversion__ if int(__subversion__) else __version__
|
|
947
1049
|
else:
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
1050
|
+
if Flag_DEBUG:
|
|
1051
|
+
currentVersion=__version__+'.'+__subversion__ if int(__subversion__) else __version__
|
|
1052
|
+
else:
|
|
1053
|
+
command=[sys.executable, '-m', 'pip', 'show', packageName]
|
|
1054
|
+
reqs = subprocess.run(command,capture_output=True)
|
|
1055
|
+
if reqs.returncode:
|
|
1056
|
+
pri.Error.red('Error in command:\n'+' '.join(command)+'\n'+reqs.stderr.decode("utf-8") )
|
|
1057
|
+
return flagOutDated,currentVersion,latestVersion
|
|
1058
|
+
printing=reqs.stdout.decode("utf-8")
|
|
1059
|
+
pri.Info.cyan( printing )
|
|
1060
|
+
r=reqs.stdout.decode("utf-8").replace('\r','').split('\n')
|
|
1061
|
+
currentVersion='none'
|
|
1062
|
+
for s in r:
|
|
1063
|
+
if 'Version: ' in s:
|
|
1064
|
+
currentVersion=s.replace('Version: ','')
|
|
1065
|
+
break
|
|
961
1066
|
if currentVersion!=__version__:
|
|
962
1067
|
message=f'Greetings, developer!\nThe version of the current instance of PaIRS_UniNa ({__version__}) is different from that installed in the present Python environment ({currentVersion})!\nYou should contact Tommaso and Gerardo if some relevant change is made by yourself!'
|
|
963
1068
|
pri.Info.yellow(f'{"-"*50}\n{message}\n{"-"*50}\n')
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
if not reqs.returncode:
|
|
967
|
-
printing=reqs.stdout.decode("utf-8")
|
|
968
|
-
pri.Info.cyan( printing )
|
|
969
|
-
r=reqs.stdout.decode("utf-8").replace('\r','').split('\n')
|
|
970
|
-
#currentVersion=r[0].replace(packageName,'').replace('(','').replace(')','').replace(' ','')
|
|
971
|
-
latestVersion=r[1].replace('Available versions: ','').split(',')[0]
|
|
1069
|
+
if Flag_ISEXE:
|
|
1070
|
+
_, latestVersion = get_package_version_urllib("PaIRS_UniNa")
|
|
972
1071
|
else:
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
command=[sys.executable, '-m', 'pip', 'list','--outdated']
|
|
1072
|
+
command=[sys.executable, '-m', 'pip', 'index', 'versions', packageName]
|
|
976
1073
|
reqs = subprocess.run(command,capture_output=True)
|
|
977
|
-
if reqs.returncode:
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
latestVersion=outDated[i+2]
|
|
1074
|
+
if not reqs.returncode:
|
|
1075
|
+
printing=reqs.stdout.decode("utf-8")
|
|
1076
|
+
pri.Info.cyan( printing )
|
|
1077
|
+
r=reqs.stdout.decode("utf-8").replace('\r','').split('\n')
|
|
1078
|
+
#currentVersion=r[0].replace(packageName,'').replace('(','').replace(')','').replace(' ','')
|
|
1079
|
+
latestVersion=r[1].replace('Available versions: ','').split(',')[0]
|
|
984
1080
|
else:
|
|
985
|
-
latestVersion=
|
|
986
|
-
|
|
1081
|
+
flagOk,latestVersion=get_package_version_urllib(packageName)
|
|
1082
|
+
if not flagOk:
|
|
1083
|
+
pri.Error.red('Error in command:\n'+' '.join(command)+'\n'+reqs.stderr.decode("utf-8") )
|
|
1084
|
+
pri.Error.red(latestVersion)
|
|
1085
|
+
latestVersion='none'
|
|
1086
|
+
|
|
1087
|
+
"""
|
|
1088
|
+
command=[sys.executable, '-m', 'pip', 'list','--outdated']
|
|
1089
|
+
reqs = subprocess.run(command,capture_output=True)
|
|
1090
|
+
if reqs.returncode:
|
|
1091
|
+
pri.Error.red('Error in command:\n'+' '.join(command)+'\n'+reqs.stderr.decode("utf-8") )
|
|
1092
|
+
return flagOutDated,currentVersion,latestVersion
|
|
1093
|
+
outDated = [r.decode().split('==')[0] for r in reqs.stdout.split()]
|
|
1094
|
+
if packageName in outDated:
|
|
1095
|
+
i=outDated.index(packageName)
|
|
1096
|
+
latestVersion=outDated[i+2]
|
|
1097
|
+
else:
|
|
1098
|
+
latestVersion=currentVersion
|
|
1099
|
+
pri.Info.cyan(f'{packageName} ({currentVersion}). Latest version available: {latestVersion}')
|
|
1100
|
+
"""
|
|
987
1101
|
#flagOutDated=1 if currentVersion!=latestVersion else 0
|
|
988
1102
|
cV_parts=[int(c) for c in currentVersion.split('.')]
|
|
989
1103
|
lV_parts=[int(c) for c in latestVersion.split('.')]
|
|
@@ -1095,6 +1209,34 @@ def optimalPivCores(totCore,nImgs,penCore=1):
|
|
|
1095
1209
|
#nPivMax=floor(totCore/nCoreMax)
|
|
1096
1210
|
return nPivMax,nCoreMax
|
|
1097
1211
|
|
|
1212
|
+
from PySide6.QtCore import qInstallMessageHandler, QtMsgType
|
|
1213
|
+
def custom_qt_message_handler(mode, context, message):
|
|
1214
|
+
if ("QPainter" in message or "paintEngine" in message):
|
|
1215
|
+
return #Silenzia questi messaggi
|
|
1216
|
+
print(message) #Altrimenti stampali normalmente (oppure loggali)
|
|
1217
|
+
qInstallMessageHandler(custom_qt_message_handler)
|
|
1218
|
+
|
|
1219
|
+
"""
|
|
1220
|
+
def custom_qt_message_handler(mode, context, message):
|
|
1221
|
+
if "QPainter" in message or "paintEngine" in message:
|
|
1222
|
+
print("\n!!! Intercepted Qt message:")
|
|
1223
|
+
print(message)
|
|
1224
|
+
print("\n*** Current Python stacktrace:")
|
|
1225
|
+
traceback.print_stack() # Questo stampa lo stack in cui è stato generato il messaggio
|
|
1226
|
+
else:
|
|
1227
|
+
print(message)
|
|
1228
|
+
qInstallMessageHandler(custom_qt_message_handler)
|
|
1229
|
+
import functools
|
|
1230
|
+
import traceback
|
|
1231
|
+
def log_qpainter_usage(func):
|
|
1232
|
+
@functools.wraps(func)
|
|
1233
|
+
def wrapper(*args, **kwargs):
|
|
1234
|
+
print(f"\n°°° Execution of {func.__name__} in {func.__module__}")
|
|
1235
|
+
traceback.print_stack(limit=4) # Mostra solo lo stack alto
|
|
1236
|
+
return func(*args, **kwargs)
|
|
1237
|
+
return wrapper
|
|
1238
|
+
"""
|
|
1239
|
+
|
|
1098
1240
|
class PaIRSApp(QApplication):
|
|
1099
1241
|
def __init__(self,*args):
|
|
1100
1242
|
super().__init__(*args)
|
|
@@ -1110,4 +1252,125 @@ class PaIRSApp(QApplication):
|
|
|
1110
1252
|
|
|
1111
1253
|
def installMessageHandler(self):
|
|
1112
1254
|
qInstallMessageHandler(self.message_handler)
|
|
1113
|
-
|
|
1255
|
+
|
|
1256
|
+
rqrdpckgs_filename=foldPaIRS+"rqrdpckgs.txt"
|
|
1257
|
+
from packaging.version import Version
|
|
1258
|
+
import importlib.metadata
|
|
1259
|
+
|
|
1260
|
+
def resetRequiredPackagesFile(filename=rqrdpckgs_filename):
|
|
1261
|
+
# Leggi il contenuto esistente
|
|
1262
|
+
try:
|
|
1263
|
+
with open(filename, "r") as f:
|
|
1264
|
+
lines = f.readlines()
|
|
1265
|
+
except FileNotFoundError:
|
|
1266
|
+
pri.Error.red(f"resetRequiredPackagesFile: File {filename} not found.")
|
|
1267
|
+
return
|
|
1268
|
+
|
|
1269
|
+
with open(filename, "w") as f:
|
|
1270
|
+
for line in lines:
|
|
1271
|
+
parts = line.strip().split()
|
|
1272
|
+
if len(parts) >= 3:
|
|
1273
|
+
pkg = parts[0]
|
|
1274
|
+
vmin = parts[1]
|
|
1275
|
+
vmax = parts[2]
|
|
1276
|
+
f.write(f"{pkg}\t{vmin}\t{vmax}\t0\n")
|
|
1277
|
+
else:
|
|
1278
|
+
pri.Error.red(f"resetRequiredPackagesFile: Skipping malformed line: {line}")
|
|
1279
|
+
|
|
1280
|
+
def to_triplet(v: Version) -> tuple[int,int,int]:
|
|
1281
|
+
r = v.release or (0,)
|
|
1282
|
+
return (r[0], r[1] if len(r) > 1 else 0, r[2] if len(r) > 2 else 0)
|
|
1283
|
+
|
|
1284
|
+
def le_ver(a: Version, b: Version) -> bool:
|
|
1285
|
+
a1,a2,a3 = to_triplet(a)
|
|
1286
|
+
b1,b2,b3 = to_triplet(b)
|
|
1287
|
+
if a1 > b1: return False
|
|
1288
|
+
if a1 < b1: return True
|
|
1289
|
+
if a2 > b2: return False
|
|
1290
|
+
if a2 < b2: return True
|
|
1291
|
+
return a3 <= b3
|
|
1292
|
+
|
|
1293
|
+
def checkRequiredPackages(self, filename=rqrdpckgs_filename, FlagDisplay=False, FlagForcePrint=False):
|
|
1294
|
+
required_packages = []
|
|
1295
|
+
vmin_list = []
|
|
1296
|
+
vmax_list = []
|
|
1297
|
+
vcurr_list = []
|
|
1298
|
+
|
|
1299
|
+
# Read file
|
|
1300
|
+
with open(filename, "r") as f:
|
|
1301
|
+
for line in f:
|
|
1302
|
+
#pri.Info.white(line)
|
|
1303
|
+
parts = line.strip().split()
|
|
1304
|
+
if len(parts) >= 4:
|
|
1305
|
+
required_packages.append(parts[0])
|
|
1306
|
+
vmin_list.append(Version(parts[1]))
|
|
1307
|
+
vmax_list.append(Version(parts[2]))
|
|
1308
|
+
vcurr_list.append(Version(parts[3]) if parts[3] != "0" else None)
|
|
1309
|
+
else:
|
|
1310
|
+
pri.Error.red(f"Malformed line: {line}")
|
|
1311
|
+
|
|
1312
|
+
Flag = False
|
|
1313
|
+
warnings = []
|
|
1314
|
+
|
|
1315
|
+
for i, pkg in enumerate(required_packages):
|
|
1316
|
+
try:
|
|
1317
|
+
installed_version = Version(importlib.metadata.version(pkg))
|
|
1318
|
+
except importlib.metadata.PackageNotFoundError:
|
|
1319
|
+
installed_version = None
|
|
1320
|
+
|
|
1321
|
+
# Update current installed version
|
|
1322
|
+
if installed_version is not None and (installed_version != vcurr_list[i] or FlagDisplay):
|
|
1323
|
+
vcurr_list[i] = installed_version
|
|
1324
|
+
Flag = True
|
|
1325
|
+
|
|
1326
|
+
# Check if within [vmin, vmax]
|
|
1327
|
+
if not (le_ver(vmin_list[i],installed_version) and le_ver(installed_version,vmax_list[i])):
|
|
1328
|
+
"""
|
|
1329
|
+
warnings.append(
|
|
1330
|
+
f"- {pkg}: installed = {installed_version}, target range = [{vmin_list[i]}, {vmax_list[i]}]"
|
|
1331
|
+
)
|
|
1332
|
+
"""
|
|
1333
|
+
warnings.append(
|
|
1334
|
+
f"- {pkg} {installed_version} not in [{vmin_list[i]}, {vmax_list[i]}]"
|
|
1335
|
+
)
|
|
1336
|
+
|
|
1337
|
+
# Show warning
|
|
1338
|
+
if len(warnings)>0: self.FlagPackIssue=True
|
|
1339
|
+
if len(warnings)>0 or FlagForcePrint:
|
|
1340
|
+
message = (
|
|
1341
|
+
"Some installed packages have a version outside the target range used to develop "
|
|
1342
|
+
"the current release of the PaIRS_UniNa package.\n\n"
|
|
1343
|
+
"This may lead to compatibility issues. If you experience unexpected behavior, "
|
|
1344
|
+
"it is recommended to either reinstall the last tested compatible versions or "
|
|
1345
|
+
f"download the executable at {EXEurl}."
|
|
1346
|
+
f" If any issue occurs, please contact the authors at {__mail__}.\n\n"
|
|
1347
|
+
#"or use the standalone executable available at:\n"
|
|
1348
|
+
#"https://pairs.unina.it/#download\n\n"
|
|
1349
|
+
"Incompatible packages:\n"
|
|
1350
|
+
+ "\n".join(warnings) +
|
|
1351
|
+
"\n\nYou may reinstall the last compatible versions using the following commands:\n\n"
|
|
1352
|
+
)
|
|
1353
|
+
for i, pkg in enumerate(required_packages):
|
|
1354
|
+
if vcurr_list[i] is not None and (not (vmin_list[i] <= vcurr_list[i] <= vmax_list[i]) or FlagForcePrint):
|
|
1355
|
+
message += (
|
|
1356
|
+
f"python -m pip uninstall {pkg}\n"
|
|
1357
|
+
f"python -m pip install {pkg}=={vmax_list[i]}\n"
|
|
1358
|
+
)
|
|
1359
|
+
|
|
1360
|
+
warningDialog(
|
|
1361
|
+
self,
|
|
1362
|
+
Message=message,
|
|
1363
|
+
flagScreenCenter=True,
|
|
1364
|
+
pixmap=icons_path + 'python_warning.png',
|
|
1365
|
+
pixmapSize=96
|
|
1366
|
+
)
|
|
1367
|
+
elif FlagDisplay:
|
|
1368
|
+
warningDialog(self, Message="All installed packages are within the expected version range.", flagScreenCenter=True,pixmap=icons_path+'greenv.png')
|
|
1369
|
+
|
|
1370
|
+
# Update file if needed
|
|
1371
|
+
if Flag:
|
|
1372
|
+
with open(filename, "w") as f:
|
|
1373
|
+
for pkg, vmin, vmax, vcurr in zip(required_packages, vmin_list, vmax_list, vcurr_list):
|
|
1374
|
+
f.write(f"{pkg}\t{vmin}\t{vmax}\t{vcurr if vcurr else 0}\n")
|
|
1375
|
+
|
|
1376
|
+
return required_packages, vmin_list, vmax_list, vcurr_list
|
PaIRS_UniNa/Process_Tab.py
CHANGED
|
@@ -724,9 +724,8 @@ class Process_Tab(gPaIRS_Tab):
|
|
|
724
724
|
#******************** Actions
|
|
725
725
|
def edit_Wind_vectors(self,wedit:QLineEdit,wlab:QLabel):
|
|
726
726
|
text=wedit.text()
|
|
727
|
-
split_text=re.split('(\d+)', text)[1:-1:2]
|
|
727
|
+
split_text=re.split(r'(\d+)', text)[1:-1:2]
|
|
728
728
|
vect=[int(i) for i in split_text]
|
|
729
|
-
tip=QToolTip(wedit)
|
|
730
729
|
FlagEmpty=len(vect)==0
|
|
731
730
|
if FlagEmpty: FlagError=True
|
|
732
731
|
else: FlagError=not all([v>=w for v,w in zip(vect[:-1],vect[1:])])
|
|
@@ -739,21 +738,18 @@ class Process_Tab(gPaIRS_Tab):
|
|
|
739
738
|
wlab.setToolTip(message)
|
|
740
739
|
wlab.setStatusTip(message)
|
|
741
740
|
"""
|
|
742
|
-
|
|
743
|
-
tip.showText(QCursor.pos(),wlab.toolTip(),wedit,QRect(),3000)
|
|
741
|
+
QToolTip.showText(QCursor.pos(),wlab.toolTip(),wedit,QRect(),3000)
|
|
744
742
|
"""
|
|
745
743
|
else:
|
|
746
744
|
wlab.setPixmap(QPixmap())
|
|
747
|
-
tip.hideText()
|
|
748
745
|
self.PROpar.VectFlag[self.Vect_widgets.index(wedit)]=not FlagError
|
|
749
|
-
return split_text, vect,
|
|
746
|
+
return split_text, vect, FlagError
|
|
750
747
|
|
|
751
748
|
def set_Wind_vectors(self,wedit:QLineEdit,wlab:QLabel,i):
|
|
752
|
-
_, vect,
|
|
753
|
-
self.set_Wind_vectors_new(i,vect,
|
|
749
|
+
_, vect, FlagError=self.edit_Wind_vectors(wedit,wlab)
|
|
750
|
+
self.set_Wind_vectors_new(i,vect,FlagError)
|
|
754
751
|
|
|
755
|
-
def set_Wind_vectors_new(self,i,vect,
|
|
756
|
-
#tip.hideText()
|
|
752
|
+
def set_Wind_vectors_new(self,i,vect,FlagError=False):
|
|
757
753
|
if not FlagError:
|
|
758
754
|
Nit_i=len(vect)
|
|
759
755
|
if Nit_i>self.PROpar.Nit:
|
|
@@ -1295,7 +1291,7 @@ class Process_Tab(gPaIRS_Tab):
|
|
|
1295
1291
|
|
|
1296
1292
|
def line_edit_IW_action(self):
|
|
1297
1293
|
text=self.ui.line_edit_IW.text()
|
|
1298
|
-
split_text=re.split('(\d+)', text)[1:-1:2]
|
|
1294
|
+
split_text=re.split(r'(\d+)', text)[1:-1:2]
|
|
1299
1295
|
vect=[int(split_text[i]) for i in (0,2,1,3)]
|
|
1300
1296
|
if len(vect)==4:
|
|
1301
1297
|
k=self.PROpar.row
|
|
@@ -1365,10 +1361,9 @@ class Process_Tab(gPaIRS_Tab):
|
|
|
1365
1361
|
item.setStatusTip('')
|
|
1366
1362
|
|
|
1367
1363
|
message='No context menu available! Please, pause processing.'
|
|
1368
|
-
tip=QToolTip(self)
|
|
1369
1364
|
toolTipDuration=self.toolTipDuration()
|
|
1370
1365
|
self.setToolTipDuration(3000)
|
|
1371
|
-
|
|
1366
|
+
QToolTip.showText(QCursor.pos(),message)
|
|
1372
1367
|
self.setToolTipDuration(toolTipDuration)
|
|
1373
1368
|
item.setToolTip(toolTip)
|
|
1374
1369
|
item.setStatusTip(toolTip)
|