modulitiz-micro 2.26.0__py311-none-any.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.
Files changed (100) hide show
  1. modulitiz_micro/ModuloBase64.py +61 -0
  2. modulitiz_micro/ModuloColorText.py +35 -0
  3. modulitiz_micro/ModuloDate.py +295 -0
  4. modulitiz_micro/ModuloFunzioni.py +58 -0
  5. modulitiz_micro/ModuloListe.py +150 -0
  6. modulitiz_micro/ModuloMeteo.py +72 -0
  7. modulitiz_micro/ModuloNumeri.py +130 -0
  8. modulitiz_micro/ModuloPyinstaller.py +29 -0
  9. modulitiz_micro/ModuloSeriale.py +61 -0
  10. modulitiz_micro/ModuloStatistiche.py +31 -0
  11. modulitiz_micro/ModuloStringhe.py +180 -0
  12. modulitiz_micro/ModuloTarghe.py +46 -0
  13. modulitiz_micro/android/ModuloAndroid.py +18 -0
  14. modulitiz_micro/android/ModuloAndroidAdb.py +48 -0
  15. modulitiz_micro/android/ModuloAndroidSim.py +130 -0
  16. modulitiz_micro/android/beans/SmsBean.py +12 -0
  17. modulitiz_micro/android/enums/AndroidSmsTypeEnum.py +17 -0
  18. modulitiz_micro/database/AbstractDatabaseService.py +13 -0
  19. modulitiz_micro/database/AbstractSql.py +49 -0
  20. modulitiz_micro/database/ModuloSqlOracle.py +19 -0
  21. modulitiz_micro/database/ModuloSqlServer.py +50 -0
  22. modulitiz_micro/database/eccezioni/EccezioneDbNoData.py +6 -0
  23. modulitiz_micro/database/mysql/AbstractBasicMysql.py +114 -0
  24. modulitiz_micro/database/mysql/ModuloMysql.py +151 -0
  25. modulitiz_micro/database/mysql/MysqlCommonConverter.py +47 -0
  26. modulitiz_micro/database/mysql/eccezioni/EccezioneMysqlOffline.py +6 -0
  27. modulitiz_micro/database/sqlite/AbstractBasicSQLite.py +114 -0
  28. modulitiz_micro/database/sqlite/ModuloSQLite.py +82 -0
  29. modulitiz_micro/eccezioni/EccezioneBase.py +7 -0
  30. modulitiz_micro/eccezioni/EccezioneCtrlC.py +7 -0
  31. modulitiz_micro/eccezioni/EccezioneRuntime.py +7 -0
  32. modulitiz_micro/eccezioni/EccezioneScheduler.py +7 -0
  33. modulitiz_micro/eccezioni/EccezioneSoNonSupportato.py +7 -0
  34. modulitiz_micro/eccezioni/http/EccezioneHttp.py +8 -0
  35. modulitiz_micro/eccezioni/http/EccezioneHttp404.py +7 -0
  36. modulitiz_micro/eccezioni/http/EccezioneHttpGeneric.py +7 -0
  37. modulitiz_micro/files/ModuloFiles.py +173 -0
  38. modulitiz_micro/files/ModuloLogging.py +69 -0
  39. modulitiz_micro/files/ModuloZip.py +42 -0
  40. modulitiz_micro/files/cache/CacheBean.py +5 -0
  41. modulitiz_micro/files/cache/CacheRam.py +29 -0
  42. modulitiz_micro/files/cache/DatabaseCache.py +91 -0
  43. modulitiz_micro/files/cache/decorators/cacheRam.py +26 -0
  44. modulitiz_micro/files/git/ModuloGit.py +15 -0
  45. modulitiz_micro/gestionedom/GestioneDom.py +44 -0
  46. modulitiz_micro/init/AbstractBasicInit.py +27 -0
  47. modulitiz_micro/init/AbstractInit.py +11 -0
  48. modulitiz_micro/keylogger/EccezioneKeyLogger.py +7 -0
  49. modulitiz_micro/keylogger/ModuloKeylogger.py +73 -0
  50. modulitiz_micro/multithreading/ModuloThread.py +26 -0
  51. modulitiz_micro/multithreading/ModuloThreadLogger.py +8 -0
  52. modulitiz_micro/multithreading/ModuloThreadWithCallbackError.py +25 -0
  53. modulitiz_micro/nlp/ModuloNlp.py +36 -0
  54. modulitiz_micro/nlp/ModuloNlpDateAndTime.py +59 -0
  55. modulitiz_micro/rete/ModuloEmail.py +69 -0
  56. modulitiz_micro/rete/ModuloNetworking.py +64 -0
  57. modulitiz_micro/rete/ModuloOpenVpn.py +15 -0
  58. modulitiz_micro/rete/http/ModuloHttp.py +114 -0
  59. modulitiz_micro/rete/http/ModuloHttpConnectionSafe.py +91 -0
  60. modulitiz_micro/rete/http/ModuloHttpUtils.py +66 -0
  61. modulitiz_micro/rete/http/beans/HttpResponseBean.py +5 -0
  62. modulitiz_micro/rete/http/decorators/catchAndRaiseHttpExceptions.py +22 -0
  63. modulitiz_micro/rete/ntp/AbstractModuloNtp.py +73 -0
  64. modulitiz_micro/rete/ntp/ModuloNtpIt.py +8 -0
  65. modulitiz_micro/rete/socketserver/AbstractBasicGetSocketServer.py +35 -0
  66. modulitiz_micro/rete/socketserver/AbstractSocketServer.py +267 -0
  67. modulitiz_micro/rete/ssl/ModuloSsl.py +56 -0
  68. modulitiz_micro/sistema/EnvVarsEnum.py +9 -0
  69. modulitiz_micro/sistema/ModuloEnvVars.py +34 -0
  70. modulitiz_micro/sistema/ModuloSystem.py +298 -0
  71. modulitiz_micro/sistema/ModuloSystemPipe.py +67 -0
  72. modulitiz_micro/social/telegram/ModuloTelegram.py +52 -0
  73. modulitiz_micro/social/telegram/ModuloTelegramSimple.py +26 -0
  74. modulitiz_micro/util/beans/conf/AbstractBasicConfBean.py +11 -0
  75. modulitiz_micro/util/beans/conf/AbstractConfBean.py +16 -0
  76. modulitiz_micro/util/beans/fileconf/AbstractBasicFileConfBean.py +11 -0
  77. modulitiz_micro/util/beans/fileconf/AbstractFileConfBean.py +13 -0
  78. modulitiz_micro/util/beans/globalvar/AbstractBasicGlobalVarBean.py +15 -0
  79. modulitiz_micro/util/beans/globalvar/AbstractGlobalVarBean.py +34 -0
  80. modulitiz_micro/util/decorators/noAwait.py +23 -0
  81. modulitiz_micro/util/pip/AbstractModuloPip.py +41 -0
  82. modulitiz_micro/util/pip/ModuloPip.py +49 -0
  83. modulitiz_micro/util/scheduler/AbstractScheduler.py +32 -0
  84. modulitiz_micro/util/spooler/AbstractSpooler.py +14 -0
  85. modulitiz_micro/util/spooler/Spooler.py +18 -0
  86. modulitiz_micro/util/spooler/beans/QueueBean.py +8 -0
  87. modulitiz_micro/util/spooler/decorators/spooler.py +49 -0
  88. modulitiz_micro/util/spooler/eccezioni/EccezioneSpooler.py +7 -0
  89. modulitiz_micro/util/spooler/eccezioni/EccezioneSpoolerFull.py +7 -0
  90. modulitiz_micro/util/unittesting/AbstractOverrideTestUtil.py +18 -0
  91. modulitiz_micro/util/unittesting/AbstractTestUtil.py +11 -0
  92. modulitiz_micro/util/unittesting/ModuloRunUnitTest.py +25 -0
  93. modulitiz_micro/util/wheel/ModuloBuildWheel.py +118 -0
  94. modulitiz_micro/util/wheel/ModuloToml.py +40 -0
  95. modulitiz_micro/util/wheel/ModuloWheel.py +12 -0
  96. modulitiz_micro-2.26.0.dist-info/LICENSE +21 -0
  97. modulitiz_micro-2.26.0.dist-info/METADATA +63 -0
  98. modulitiz_micro-2.26.0.dist-info/RECORD +100 -0
  99. modulitiz_micro-2.26.0.dist-info/WHEEL +5 -0
  100. modulitiz_micro-2.26.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,26 @@
1
+ import threading
2
+
3
+ from modulitiz_micro.files.ModuloLogging import ModuloLogging
4
+ from modulitiz_micro.multithreading.ModuloThreadLogger import ModuloThreadLogger
5
+ from modulitiz_micro.multithreading.ModuloThreadWithCallbackError import ModuloThreadWithCallbackError
6
+
7
+
8
+ class ModuloThread(object):
9
+ @staticmethod
10
+ def startDaemon(logger:ModuloLogging,funzione,args:tuple)->ModuloThreadLogger:
11
+ d=ModuloThreadLogger(logger,name='th__'+funzione.__name__,target=funzione,args=args,daemon=True)
12
+ d.start()
13
+ return d
14
+ @staticmethod
15
+ def startDaemonWithCallbackError(callbackError,funzione,args:tuple)->ModuloThreadWithCallbackError:
16
+ d=ModuloThreadWithCallbackError(callbackError,name='th__'+funzione.__name__,target=funzione,args=args,daemon=True)
17
+ d.start()
18
+ return d
19
+
20
+ @staticmethod
21
+ def numeroThreadsAttivi()->int:
22
+ """
23
+ Non e' incluso il main, ovviamente.
24
+ Se usi pydev debugger devi sottrarre altri 2 o 3 threads
25
+ """
26
+ return threading.active_count()-1
@@ -0,0 +1,8 @@
1
+ from modulitiz_micro.files.ModuloLogging import ModuloLogging
2
+ from modulitiz_micro.multithreading.ModuloThreadWithCallbackError import ModuloThreadWithCallbackError
3
+
4
+
5
+ class ModuloThreadLogger(ModuloThreadWithCallbackError):
6
+
7
+ def __init__(self,logger:ModuloLogging,**kwargs):
8
+ super().__init__(lambda ex:logger.exception('Eccezione nel thread:'),**kwargs)
@@ -0,0 +1,25 @@
1
+ import threading
2
+
3
+
4
+ class ModuloThreadWithCallbackError(threading.Thread):
5
+ """
6
+ This class should always be used in preference to threading.Thread.
7
+
8
+ The interface provided by this class is identical to that of threading.Thread,
9
+ however, if an exception occurs in the thread the callback function is called,
10
+ rather than printed to stderr.
11
+
12
+ This is important in daemon style applications where stderr is redirected to /dev/null.
13
+ """
14
+
15
+ def __init__(self,callbackError,**kwargs):
16
+ super().__init__(**kwargs)
17
+ self.callbackError=callbackError
18
+ self._realRun=self.run
19
+ self.run=self.__wrapRun
20
+
21
+ def __wrapRun(self):
22
+ try:
23
+ self._realRun()
24
+ except Exception as ex:
25
+ self.callbackError(ex)
@@ -0,0 +1,36 @@
1
+ class ModuloNlp(object):
2
+
3
+ @staticmethod
4
+ def giornoRelativoToParola(giornoRel:int)->str|None:
5
+ match giornoRel:
6
+ case -1: return "ieri"
7
+ case 0: return "oggi"
8
+ case 1: return "domani"
9
+ case 2: return "dopodomani"
10
+ case _: return None
11
+
12
+ @staticmethod
13
+ def giornoRelativoToNum(giornoRel:str)->int|None:
14
+ match giornoRel:
15
+ case "ieri": return -1
16
+ case "oggi": return 0
17
+ case "domani": return 1
18
+ case "dopodomani": return 2
19
+ case _: return None
20
+
21
+ @staticmethod
22
+ def verboEssere(isPassato:bool)->str:
23
+ if isPassato:
24
+ return "era"
25
+ return "è"
26
+
27
+ @staticmethod
28
+ def articolo(isDeterminativo:bool,isMaschile:bool)->str:
29
+ if isDeterminativo:
30
+ if isMaschile:
31
+ return "il"
32
+ return "la"
33
+ if isMaschile:
34
+ return "un"
35
+ return "una"
36
+
@@ -0,0 +1,59 @@
1
+ from modulitiz_micro.ModuloDate import ModuloDate
2
+ from modulitiz_micro.ModuloNumeri import ModuloNumeri
3
+ from modulitiz_micro.nlp.ModuloNlp import ModuloNlp
4
+
5
+
6
+ class ModuloNlpDateAndTime(object):
7
+ @staticmethod
8
+ def dateToString(data,anno:str)->str:
9
+ dataStr=ModuloDate.dateToString(data,"%w %A %d %B")
10
+ numGiornoSett,giornoSett,giorno,mese=dataStr.split(" ")
11
+ # sistemo grammaticalmente gli articoli, verbi, ...
12
+ numGiornoSett=int(numGiornoSett)
13
+ giorno=int(giorno)
14
+ articoloGiornoMese="il "
15
+ giornoParola=giorno
16
+ if giorno in (1,8,11):
17
+ articoloGiornoMese="l'"
18
+ giornoParola=ModuloNumeri.numberToWord(giorno)
19
+ verbo=ModuloNlp.verboEssere(data<ModuloDate.now())
20
+ articoloGiornoSett=ModuloNlp.articolo(False,numGiornoSett!=0)
21
+ output=f"{articoloGiornoMese}{giornoParola} {mese}{anno} {verbo} {articoloGiornoSett} {giornoSett}"
22
+ output=output.lower()
23
+ return output
24
+
25
+ @classmethod
26
+ def minutesToTimeRelative(cls,minutes:int,arrotonda:bool)->str:
27
+ prefixTempo=""
28
+ minutes,hoursDiff,hoursWord=cls.__minutesToHours(minutes)
29
+ # minuti
30
+ minutesWord=minutes
31
+ if minutes==1:
32
+ minutesWord="un"
33
+ elif 10<minutes<60:
34
+ if arrotonda is True and minutes%10!=0:
35
+ prefixTempo=" circa"
36
+ minutes=round(minutes,-1)
37
+ minutesWord=minutes
38
+ output="Fino a"+prefixTempo
39
+ if hoursDiff>0:
40
+ output+=" %s or%s"%(hoursWord,("a" if hoursDiff==1 else "e"))
41
+ if minutes>0:
42
+ output+=" e"
43
+ if minutes>0:
44
+ output+=" %s minut%s"%(minutesWord,("o" if minutes==1 else "i"))
45
+ return output
46
+
47
+ @staticmethod
48
+ def __minutesToHours(minutes:int)->tuple:
49
+ hoursDiff=0
50
+ hoursWord=""
51
+ if minutes<60:
52
+ return minutes,hoursDiff,hoursWord
53
+ hoursDiff=minutes//60
54
+ minutes=minutes%60
55
+ if hoursDiff==1:
56
+ hoursWord="un"
57
+ else:
58
+ hoursWord=hoursDiff
59
+ return minutes,hoursDiff,hoursWord
@@ -0,0 +1,69 @@
1
+ import smtplib
2
+
3
+ from modulitiz_micro.ModuloDate import ModuloDate
4
+ from modulitiz_micro.ModuloListe import ModuloListe
5
+ from modulitiz_micro.ModuloStringhe import ModuloStringhe
6
+
7
+
8
+ class ModuloEmail(object):
9
+ SERVER_GOOGLE_INVIO=('smtp.gmail.com',smtplib.SMTP_SSL_PORT)
10
+ SERVER_VIRGILIO_INVIO=('out.virgilio.it',smtplib.SMTP_SSL_PORT)
11
+
12
+ def __init__(self,credenzialiServer:tuple,isDebug:bool=False):
13
+ self.credenzialiServer=credenzialiServer
14
+ self.isDebug=isDebug
15
+ self.connEmail=None
16
+ self.utente=None
17
+ self.isLogged=False
18
+
19
+ def login(self,utente:str|None=None,password:str|None=None):
20
+ if self.isLogged:
21
+ return
22
+ self.connEmail=smtplib.SMTP_SSL(*self.credenzialiServer)
23
+ if self.isDebug:
24
+ self.connEmail.set_debuglevel(1)
25
+ # se serve setto l'autenticazione
26
+ if utente is not None and password is not None:
27
+ self.utente=utente
28
+ self.connEmail.login(utente,password)
29
+ self.isLogged=True
30
+
31
+ def inviaEmail(self, mittente:str|None,destinatari, oggetto:str, messaggio:str,
32
+ isHtml:bool, dataInvio=ModuloDate.now(), cc=None, ccn=None)->dict:
33
+ # controllo i parametri
34
+ dataInvio=ModuloDate.dateToString(dataInvio)
35
+ if isinstance(destinatari, str):
36
+ destinatari=[destinatari]
37
+ if mittente is None:
38
+ mittente=self.utente
39
+ domain=self.utente.split("@")[-1]
40
+ messageId=f"{ModuloDate.getSecs()}@{domain}"
41
+ # creo il messaggio
42
+ message=f"""Date: {dataInvio}
43
+ From: {mittente}
44
+ Subject: {oggetto}
45
+ To: {", ".join(destinatari)}
46
+ Message-ID: <{messageId}>
47
+ """
48
+ if not ModuloListe.isEmpty(cc):
49
+ message+=("Cc: "+", ".join(cc))+"\n"
50
+ if not ModuloListe.isEmpty(ccn):
51
+ message+=("Bcc: "+", ".join(ccn))+"\n"
52
+ message+="Content-Type: text/html;\n"
53
+ # converto il messaggio in formato html
54
+ if not isHtml:
55
+ messaggio=ModuloStringhe.normalizzaEol(messaggio).replace("\n","<br/>\n")
56
+ messaggio=messaggio.encode(ModuloStringhe.CODIFICA_ASCII,"xmlcharrefreplace").decode(ModuloStringhe.CODIFICA_UTF8)
57
+ message+="\n"+messaggio
58
+ # invio la mail
59
+ try:
60
+ return self.connEmail.sendmail(mittente,destinatari,message)
61
+ except smtplib.SMTPServerDisconnected as ex:
62
+ return {"":str(ex)}
63
+
64
+ def close(self):
65
+ if self.connEmail is None:
66
+ return
67
+ self.connEmail.quit()
68
+ self.connEmail=None
69
+ self.isLogged=False
@@ -0,0 +1,64 @@
1
+ import os
2
+ import socket
3
+ from contextlib import closing
4
+ from uuid import getnode
5
+
6
+ from _socket import gaierror
7
+
8
+ from modulitiz_micro.ModuloListe import ModuloListe
9
+ from modulitiz_micro.ModuloStringhe import ModuloStringhe
10
+ from modulitiz_micro.eccezioni.EccezioneRuntime import EccezioneRuntime
11
+ from modulitiz_micro.sistema.ModuloSystem import ModuloSystem
12
+
13
+
14
+ class ModuloNetworking(object):
15
+ @staticmethod
16
+ def getMacAddress()->str:
17
+ mac=("%012X" % getnode())
18
+ return mac
19
+
20
+ @staticmethod
21
+ def getIp()->str|None:
22
+ sockObj = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
23
+ sockObj.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
24
+ # doesn't even have to be reachable
25
+ try:
26
+ sockObj.connect(('255.255.255.255', 1))
27
+ indirizzoIp = sockObj.getsockname()[0]
28
+ except gaierror:
29
+ indirizzoIp = None
30
+ finally:
31
+ sockObj.close()
32
+ return indirizzoIp
33
+
34
+ @staticmethod
35
+ def isHttpPortOpen(host:str|None,port:int)->bool:
36
+ # controllo host
37
+ if host is None:
38
+ host="127.0.0.1"
39
+ # controllo porta
40
+ with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
41
+ if sock.connect_ex((host, port)) == 0:
42
+ return True
43
+ return False
44
+
45
+ @staticmethod
46
+ def checkPing(indirizzoIp:str)->bool:
47
+ # costruisco il comando a seconda del sistema operativo
48
+ comando="ping "
49
+ if ModuloSystem.isWindows():
50
+ comando+="-n"
51
+ elif os.name=='posix':
52
+ comando+="-c"
53
+ else:
54
+ raise EccezioneRuntime("Tipologia del sistema operativo non riconosciuta: "+os.name)
55
+ comando+=" 1 " + indirizzoIp
56
+ # eseguo il comando
57
+ outputComando=ModuloStringhe.normalizzaEol(ModuloSystem.systemCallReturnOutput(comando,None))
58
+ righe=outputComando.split("\n")
59
+ righe=ModuloListe.eliminaElementiVuoti(righe)
60
+ for riga in righe:
61
+ if ModuloStringhe.contains(riga, "%"):
62
+ numPacchettiPersi=int(riga.split("=")[1].split("(")[0].strip())
63
+ return numPacchettiPersi==0
64
+ return False
@@ -0,0 +1,15 @@
1
+ from modulitiz_micro.sistema.ModuloSystem import ModuloSystem
2
+
3
+
4
+ class ModuloOpenVpn(object):
5
+ def __init__(self,percorsoOpenVpn:str):
6
+ self.__percorsoOpenVpn=percorsoOpenVpn
7
+
8
+ def startVpn(self,isOpenVpnAlreadyRunning:bool,filenameOvpn:str):
9
+ """
10
+ Send a command to start vpn to a new or already running instance of the GUI.
11
+ https://community.openvpn.net/openvpn/wiki/OpenVPN-GUI-New#gui-help
12
+ """
13
+ subCmd="--command connect" if isOpenVpnAlreadyRunning else "--connect"
14
+ cmd=r'start "" "{}" {} {}.ovpn'.format(self.__percorsoOpenVpn,subCmd,filenameOvpn)
15
+ ModuloSystem.systemCallWaitAndClose(cmd,False)
@@ -0,0 +1,114 @@
1
+ import gzip
2
+ import logging
3
+ import ssl
4
+ import urllib
5
+ from urllib.parse import urlencode
6
+ from urllib.request import Request
7
+
8
+ import brotli
9
+
10
+ from modulitiz_micro.ModuloBase64 import ModuloBase64
11
+ from modulitiz_micro.ModuloStringhe import ModuloStringhe
12
+ from modulitiz_micro.eccezioni.EccezioneRuntime import EccezioneRuntime
13
+ from modulitiz_micro.files.ModuloLogging import ModuloLogging
14
+ from modulitiz_micro.rete.http.ModuloHttpConnectionSafe import ModuloHttpConnectionSafe
15
+ from modulitiz_micro.rete.http.beans.HttpResponseBean import HttpResponseBean
16
+ from modulitiz_micro.rete.http.decorators.catchAndRaiseHttpExceptions import catchAndRaiseHttpExceptions
17
+
18
+
19
+ class ModuloHttp(object):
20
+ """
21
+ Utility per gestione richieste di rete secondo il protocollo HTTP.
22
+ """
23
+
24
+ UA_ANDROID="Mozilla/5.0 (Linux; Android 12.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Mobile Safari/537.36"
25
+
26
+ UA_MACOS_CHROME="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
27
+ UA_WINDOWS_CHROME="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
28
+ UA_WINDOWS_FIREFOX="Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0"
29
+
30
+ UAS=[UA_MACOS_CHROME,UA_WINDOWS_CHROME,UA_WINDOWS_FIREFOX]
31
+
32
+ URL_CERCA_GOOGLE="https://www.google.it/search?q="
33
+ URLS_GET_IP=('https://ipecho.net/plain','https://ipinfo.io/ip','https://api.ipify.org')
34
+
35
+ REGEX_INDIRIZZO_IP=r"\b(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\b"
36
+
37
+ STATUS_OK=200
38
+ STATUS_OK_PARTIAL_CONTENT=206
39
+
40
+
41
+ def __init__(self,url:str,logger:ModuloLogging|None,useProxy:bool=False):
42
+ logging.getLogger("urllib3").propagate=False
43
+
44
+ self.__requestObj=Request(url)
45
+ self.__logger=logger
46
+
47
+ self.setUserAgent(self.UA_WINDOWS_FIREFOX)
48
+ self.addHeader('Accept-Encoding','gzip, deflate, br') # questo serve per ridurre la dimensione della risposta
49
+ if useProxy is True:
50
+ self.addHeader('Origin','localhost')
51
+ self.connectionSafe=ModuloHttpConnectionSafe(self.__logger)
52
+ self.postData=None
53
+
54
+ def doGet(self,retries:int,ignoreCerts:bool=False)->HttpResponseBean:
55
+ """
56
+ Esegue una richiesta di tipo GET
57
+ """
58
+ if retries==0:
59
+ return self.__getOrPost(True,ignoreCerts)
60
+ return self.connectionSafe.run(retries,0,self.__getOrPost,True,ignoreCerts)
61
+
62
+ def doPost(self, postData:dict, retries:int,ignoreCerts:bool=False)->HttpResponseBean:
63
+ """
64
+ Esegue una richiesta di tipo POST
65
+ """
66
+ self.postData=postData
67
+ if retries==0:
68
+ return self.__getOrPost(False,ignoreCerts)
69
+ return self.connectionSafe.run(retries,0,self.__getOrPost,False,ignoreCerts)
70
+
71
+ @catchAndRaiseHttpExceptions
72
+ def __getOrPost(self, isGet:bool,ignoreCerts:bool)->HttpResponseBean:
73
+ if not isGet:
74
+ postData=urlencode(self.postData).encode()
75
+ self.__requestObj.data=postData
76
+ # ignoro certificati
77
+ ctx=None
78
+ if ignoreCerts:
79
+ ctx=ssl.create_default_context()
80
+ ctx.check_hostname=False
81
+ ctx.verify_mode=ssl.CERT_NONE
82
+ with urllib.request.urlopen(self.__requestObj,context=ctx) as response:
83
+ responseBody=response.read()
84
+ responseHeaders=response.info()
85
+ status=response.status
86
+ # se il server manda il contenuto in formato compresso lo decomprimo
87
+ contentEncoding=responseHeaders.get('Content-Encoding')
88
+ if contentEncoding=="gzip":
89
+ responseBody=gzip.decompress(responseBody)
90
+ elif contentEncoding=="br":
91
+ responseBody=brotli.decompress(responseBody)
92
+ elif contentEncoding is not None and contentEncoding!= "deflate":
93
+ raise EccezioneRuntime("Codifica '"+contentEncoding+"' non gestita.")
94
+ return HttpResponseBean(status,responseBody,responseHeaders)
95
+
96
+ # opzioni aggiuntive
97
+ def addHeader(self,nome:str,valore):
98
+ if ModuloStringhe.isEmpty(valore):
99
+ return
100
+ self.__requestObj.add_header(nome,valore)
101
+
102
+ def setUserAgent(self,userAgent:str=None):
103
+ if ModuloStringhe.isEmpty(userAgent):
104
+ userAgent=self.UA_ANDROID
105
+ else:
106
+ userAgent=userAgent.strip()
107
+ self.addHeader('User-Agent',userAgent)
108
+
109
+ def setDownloadRange(self,inizio:int,fine:int):
110
+ self.addHeader('Range',"bytes="+str(inizio)+"-"+str(fine))
111
+
112
+ def setAuthenticationBasic(self,username:str,password:str):
113
+ authStr=ModuloBase64.codificaStr('%s:%s' % (username, password))
114
+ self.addHeader('Authorization',"Basic "+authStr)
@@ -0,0 +1,91 @@
1
+ import socket
2
+ import time
3
+ from urllib.error import URLError
4
+
5
+ import requests
6
+
7
+ from modulitiz_micro.ModuloFunzioni import ModuloFunzioni
8
+ from modulitiz_micro.ModuloStringhe import ModuloStringhe
9
+ from modulitiz_micro.eccezioni.http.EccezioneHttpGeneric import EccezioneHttpGeneric
10
+ from modulitiz_micro.files.ModuloLogging import ModuloLogging
11
+
12
+
13
+ class ModuloHttpConnectionSafe(object):
14
+ """
15
+ Utility che serve per gestire eventuali errori di rete e riprova a fare la richiesta in caso di errore
16
+ """
17
+
18
+ def __init__(self,logger: ModuloLogging|None):
19
+ self.__logger=logger
20
+
21
+ self.isLoggerEnabled=self.__logger is not None
22
+ self.contaTentativi=0
23
+ self.nomeFunzChiamanti=[]
24
+ self.msgFunzChiamanti=None
25
+
26
+ def run(self, retries:int,retriesBeforeNotify: int, funzione, *args,**kwargs):
27
+ """
28
+ se 'retries' e' = -1 allora continua a provare all'infinito
29
+ se 'retriesBeforeNotify' e' = 0 allora in caso di errore di rete notifica subito
30
+ """
31
+ ritorno = None
32
+ while self._buildIf(self.contaTentativi,retries):
33
+ try:
34
+ ritorno = funzione(*args,**kwargs)
35
+ self.contaTentativi = -1
36
+ except (EccezioneHttpGeneric,ConnectionError, TimeoutError, URLError,
37
+ requests.exceptions.ConnectionError, socket.gaierror) as ex:
38
+ # controllo il tipo di errore
39
+ ModuloHttpConnectionSafe.__checkCodeExc(ex)
40
+ # gestisco l'assenza di connessione
41
+ self.contaTentativi += 1
42
+ # scrivo un messaggio di avviso
43
+ if retriesBeforeNotify == 0 or self.contaTentativi >= retriesBeforeNotify:
44
+ self.__buildMsgAndNotify()
45
+ ModuloHttpConnectionSafe.__dynamicPauseOrRaiseExc(self.contaTentativi, ex)
46
+ self.contaTentativi=0
47
+ self.nomeFunzChiamanti.clear()
48
+ return ritorno
49
+
50
+ @staticmethod
51
+ def _buildIf(contaTentativi:int,retries:int)->bool:
52
+ return contaTentativi >= 0 and (retries==-1 or contaTentativi<retries)
53
+
54
+ def __buildMsgAndNotify(self):
55
+ if not self.nomeFunzChiamanti:
56
+ self.msgFunzChiamanti="Errore di connessione nella funzione "+ModuloFunzioni.getFunctionName(1)+"()"
57
+ i=0
58
+ while -1<i<2:
59
+ nomeFunz = ModuloFunzioni.getFunctionName(i+2)
60
+ if not ModuloStringhe.isEmpty(nomeFunz):
61
+ self.msgFunzChiamanti += f", chiamata da {nomeFunz}()"
62
+ i+=1
63
+ else:
64
+ i=-1
65
+ msg=self.msgFunzChiamanti+f"; tentativo numero: {self.contaTentativi}"
66
+ if self.isLoggerEnabled:
67
+ self.__logger.error(msg)
68
+ else:
69
+ print(msg)
70
+
71
+ @staticmethod
72
+ def __checkCodeExc(ex: Exception):
73
+ try:
74
+ codiceErrore = ex.code
75
+ except AttributeError:
76
+ codiceErrore = 0
77
+ if codiceErrore in (404, 500):
78
+ raise ex
79
+
80
+ @staticmethod
81
+ def __dynamicPauseOrRaiseExc(contaTentativi: int, ex: Exception):
82
+ if 0 < contaTentativi <= 20:
83
+ time.sleep(10)
84
+ elif 20 < contaTentativi <= 30:
85
+ time.sleep(60)
86
+ elif 20 < contaTentativi <= 50:
87
+ time.sleep(60 * 2)
88
+ elif 50 < contaTentativi <= 100:
89
+ time.sleep(60 * 5)
90
+ else:
91
+ raise ex
@@ -0,0 +1,66 @@
1
+ import json
2
+ import random
3
+ from urllib.parse import quote_plus
4
+ from urllib.parse import unquote_plus
5
+
6
+ import requests
7
+
8
+ from modulitiz_micro.ModuloStringhe import ModuloStringhe
9
+ from modulitiz_micro.eccezioni.http.EccezioneHttpGeneric import EccezioneHttpGeneric
10
+ from modulitiz_micro.files.ModuloLogging import ModuloLogging
11
+ from modulitiz_micro.rete.http.ModuloHttp import ModuloHttp
12
+ from modulitiz_micro.rete.http.ModuloHttpConnectionSafe import ModuloHttpConnectionSafe
13
+ from modulitiz_micro.rete.http.decorators.catchAndRaiseHttpExceptions import catchAndRaiseHttpExceptions
14
+
15
+
16
+ class ModuloHttpUtils(object):
17
+ @staticmethod
18
+ def isUrlAvailable(logger:ModuloLogging|None,url:str,retries:int,ignoreCerts:bool=False) -> bool:
19
+ if retries!=0:
20
+ connectionSafe=ModuloHttpConnectionSafe(logger)
21
+ return connectionSafe.run(retries,0,ModuloHttpUtils.__isUrlAvailable,url,ignoreCerts)
22
+ try:
23
+ return ModuloHttpUtils.__isUrlAvailable(url,ignoreCerts)
24
+ except EccezioneHttpGeneric:
25
+ return False
26
+
27
+ @staticmethod
28
+ @catchAndRaiseHttpExceptions
29
+ def __isUrlAvailable(url:str,ignoreCerts:bool) -> bool:
30
+ with requests.get(url,stream=True,verify=(not ignoreCerts)) as response:
31
+ return response.status_code==ModuloHttp.STATUS_OK
32
+
33
+ @staticmethod
34
+ def getIp() -> str|None:
35
+ url=random.choice(ModuloHttp.URLS_GET_IP)
36
+ http=ModuloHttp(url,None)
37
+ try:
38
+ response=http.doGet(2,False)
39
+ except EccezioneHttpGeneric:
40
+ return None
41
+ if response is None:
42
+ return None
43
+ return response.responseBody.decode(ModuloStringhe.CODIFICA_UTF8)
44
+
45
+ @classmethod
46
+ def translate(cls,langFrom:str|None,langTo:str,msg:str) -> str|None:
47
+ if langFrom is None:
48
+ langFrom="auto"
49
+ msg=cls.encodeUrl(msg)
50
+ url=f'https://translate.googleapis.com/translate_a/single?client=gtx&sl={langFrom}&tl={langTo}&dt=t&q={msg}'
51
+ http=ModuloHttp(url,None)
52
+ try:
53
+ response=http.doGet(3,False)
54
+ except EccezioneHttpGeneric:
55
+ return None
56
+ responseText=response.responseBody.decode(ModuloStringhe.CODIFICA_UTF8)
57
+ result=json.loads(responseText)
58
+ output="".join(x[0] for x in result[0])
59
+ return output
60
+
61
+ @staticmethod
62
+ def encodeUrl(url: str) -> str:
63
+ return quote_plus(url)
64
+ @staticmethod
65
+ def decodeUrl(url: str) -> str:
66
+ return unquote_plus(url)
@@ -0,0 +1,5 @@
1
+ class HttpResponseBean(object):
2
+ def __init__(self,status:int,responseBody:bytes,responseHeaders:dict):
3
+ self.status=status
4
+ self.responseBody=responseBody
5
+ self.responseHeaders=responseHeaders
@@ -0,0 +1,22 @@
1
+ import socket
2
+ from functools import wraps
3
+ from urllib.error import URLError
4
+
5
+ import requests
6
+
7
+ from modulitiz_micro.eccezioni.http.EccezioneHttpGeneric import EccezioneHttpGeneric
8
+
9
+
10
+ def catchAndRaiseHttpExceptions(funzione):
11
+ """
12
+ Cattura tutte le eccezioni http di vario tipo e rilancia un'eccezione custom
13
+ """
14
+
15
+ @wraps(funzione)
16
+ def wrapped(*args,**kwargs):
17
+ try:
18
+ return funzione(*args,**kwargs)
19
+ except (ConnectionError,TimeoutError,URLError,
20
+ requests.exceptions.ConnectionError,socket.gaierror) as ex:
21
+ raise EccezioneHttpGeneric() from ex
22
+ return wrapped
@@ -0,0 +1,73 @@
1
+ import socket
2
+ import struct
3
+ from abc import ABC
4
+
5
+ from modulitiz_micro.ModuloDate import ModuloDate
6
+ from modulitiz_micro.eccezioni.http.EccezioneHttpGeneric import EccezioneHttpGeneric
7
+ from modulitiz_micro.files.ModuloLogging import ModuloLogging
8
+ from modulitiz_micro.rete.http.ModuloHttpConnectionSafe import ModuloHttpConnectionSafe
9
+ from modulitiz_micro.rete.http.decorators.catchAndRaiseHttpExceptions import catchAndRaiseHttpExceptions
10
+
11
+
12
+ class AbstractModuloNtp(ABC):
13
+ REFRESH_CACHE_EVERY_SECS=4*3600*1000 # frequenza richiesta NTP, l'rpi sballa di 45 minuti ogni 24 ore
14
+ OFFSET_MILLIS=1 # offset correzione errore
15
+ TIMEOUT=10
16
+
17
+ __PORTA=123 # numero della porta (UDP)
18
+ __BUF=1024
19
+ __TIME1970=2208988800 # reference time, secondi da 1900-01-01 00:00:00 a 1970-01-01 00:00:00 = 70 anni
20
+ __MSG=('\x1b' + 47 * '\0').encode()
21
+
22
+
23
+ def __init__(self,host:str,logger:ModuloLogging):
24
+ self.logger=logger
25
+ self.connectionSafe = ModuloHttpConnectionSafe(logger)
26
+ self.host=host
27
+ self.lastNtpResponse=0
28
+ self.lastNtpTimestampUtc=0
29
+
30
+ def getTimestampUtcFromNtp(self,useCache:bool=True,retryIfError:bool=True)->int:
31
+ if useCache is True and self.lastNtpResponse!=0:
32
+ # controllo se e' passato poco tempo dall'ultima chiamata ntp
33
+ diffMillisLastResponse=(ModuloDate.getMillis()-self.lastNtpResponse)
34
+ if diffMillisLastResponse<self.REFRESH_CACHE_EVERY_SECS:
35
+ # calcolo l'ora attuale usando il cronometro interno
36
+ return self.lastNtpTimestampUtc+diffMillisLastResponse+self.OFFSET_MILLIS
37
+ # invio la richiesta e in caso di errore...
38
+ if not retryIfError:
39
+ #... uso il cronometro interno
40
+ try:
41
+ timestampUtc=self.__ntpSendPacket()
42
+ except EccezioneHttpGeneric:
43
+ timestampUtc=None
44
+ else:
45
+ #... riprovo
46
+ timestampUtc=self.connectionSafe.run(1,3,self.__ntpSendPacket)
47
+ if timestampUtc is None:
48
+ diffMillisLastResponse=(ModuloDate.getMillis()-self.lastNtpResponse)
49
+ return self.lastNtpTimestampUtc+diffMillisLastResponse+self.OFFSET_MILLIS
50
+ timestampUtc=timestampUtc*1000
51
+ # successo
52
+ self.lastNtpResponse=ModuloDate.getMillis()
53
+ self.lastNtpTimestampUtc=timestampUtc
54
+ return self.lastNtpTimestampUtc
55
+
56
+ def getDatetimeFromNtp(self,useCache:bool=True,retryIfError:bool=True):
57
+ tsSec=self.getTimestampUtcFromNtp(useCache,retryIfError)//1000
58
+ return ModuloDate.timestampUtcToDate(tsSec)
59
+
60
+ @catchAndRaiseHttpExceptions
61
+ def __ntpSendPacket(self)->int:
62
+ # connect to server
63
+ client=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
64
+ client.settimeout(self.TIMEOUT)
65
+ client.sendto(self.__MSG,(self.host,self.__PORTA))
66
+ # ricevo i dati
67
+ response=client.recvfrom(self.__BUF)[0]
68
+ # chiudo la socket
69
+ client.close()
70
+ # estraggo il timestamp
71
+ tsSec=struct.unpack("!12I",response)[10]
72
+ tsSec-=self.__TIME1970
73
+ return tsSec