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.
- modulitiz_micro/ModuloBase64.py +61 -0
- modulitiz_micro/ModuloColorText.py +35 -0
- modulitiz_micro/ModuloDate.py +295 -0
- modulitiz_micro/ModuloFunzioni.py +58 -0
- modulitiz_micro/ModuloListe.py +150 -0
- modulitiz_micro/ModuloMeteo.py +72 -0
- modulitiz_micro/ModuloNumeri.py +130 -0
- modulitiz_micro/ModuloPyinstaller.py +29 -0
- modulitiz_micro/ModuloSeriale.py +61 -0
- modulitiz_micro/ModuloStatistiche.py +31 -0
- modulitiz_micro/ModuloStringhe.py +180 -0
- modulitiz_micro/ModuloTarghe.py +46 -0
- modulitiz_micro/android/ModuloAndroid.py +18 -0
- modulitiz_micro/android/ModuloAndroidAdb.py +48 -0
- modulitiz_micro/android/ModuloAndroidSim.py +130 -0
- modulitiz_micro/android/beans/SmsBean.py +12 -0
- modulitiz_micro/android/enums/AndroidSmsTypeEnum.py +17 -0
- modulitiz_micro/database/AbstractDatabaseService.py +13 -0
- modulitiz_micro/database/AbstractSql.py +49 -0
- modulitiz_micro/database/ModuloSqlOracle.py +19 -0
- modulitiz_micro/database/ModuloSqlServer.py +50 -0
- modulitiz_micro/database/eccezioni/EccezioneDbNoData.py +6 -0
- modulitiz_micro/database/mysql/AbstractBasicMysql.py +114 -0
- modulitiz_micro/database/mysql/ModuloMysql.py +151 -0
- modulitiz_micro/database/mysql/MysqlCommonConverter.py +47 -0
- modulitiz_micro/database/mysql/eccezioni/EccezioneMysqlOffline.py +6 -0
- modulitiz_micro/database/sqlite/AbstractBasicSQLite.py +114 -0
- modulitiz_micro/database/sqlite/ModuloSQLite.py +82 -0
- modulitiz_micro/eccezioni/EccezioneBase.py +7 -0
- modulitiz_micro/eccezioni/EccezioneCtrlC.py +7 -0
- modulitiz_micro/eccezioni/EccezioneRuntime.py +7 -0
- modulitiz_micro/eccezioni/EccezioneScheduler.py +7 -0
- modulitiz_micro/eccezioni/EccezioneSoNonSupportato.py +7 -0
- modulitiz_micro/eccezioni/http/EccezioneHttp.py +8 -0
- modulitiz_micro/eccezioni/http/EccezioneHttp404.py +7 -0
- modulitiz_micro/eccezioni/http/EccezioneHttpGeneric.py +7 -0
- modulitiz_micro/files/ModuloFiles.py +173 -0
- modulitiz_micro/files/ModuloLogging.py +69 -0
- modulitiz_micro/files/ModuloZip.py +42 -0
- modulitiz_micro/files/cache/CacheBean.py +5 -0
- modulitiz_micro/files/cache/CacheRam.py +29 -0
- modulitiz_micro/files/cache/DatabaseCache.py +91 -0
- modulitiz_micro/files/cache/decorators/cacheRam.py +26 -0
- modulitiz_micro/files/git/ModuloGit.py +15 -0
- modulitiz_micro/gestionedom/GestioneDom.py +44 -0
- modulitiz_micro/init/AbstractBasicInit.py +27 -0
- modulitiz_micro/init/AbstractInit.py +11 -0
- modulitiz_micro/keylogger/EccezioneKeyLogger.py +7 -0
- modulitiz_micro/keylogger/ModuloKeylogger.py +73 -0
- modulitiz_micro/multithreading/ModuloThread.py +26 -0
- modulitiz_micro/multithreading/ModuloThreadLogger.py +8 -0
- modulitiz_micro/multithreading/ModuloThreadWithCallbackError.py +25 -0
- modulitiz_micro/nlp/ModuloNlp.py +36 -0
- modulitiz_micro/nlp/ModuloNlpDateAndTime.py +59 -0
- modulitiz_micro/rete/ModuloEmail.py +69 -0
- modulitiz_micro/rete/ModuloNetworking.py +64 -0
- modulitiz_micro/rete/ModuloOpenVpn.py +15 -0
- modulitiz_micro/rete/http/ModuloHttp.py +114 -0
- modulitiz_micro/rete/http/ModuloHttpConnectionSafe.py +91 -0
- modulitiz_micro/rete/http/ModuloHttpUtils.py +66 -0
- modulitiz_micro/rete/http/beans/HttpResponseBean.py +5 -0
- modulitiz_micro/rete/http/decorators/catchAndRaiseHttpExceptions.py +22 -0
- modulitiz_micro/rete/ntp/AbstractModuloNtp.py +73 -0
- modulitiz_micro/rete/ntp/ModuloNtpIt.py +8 -0
- modulitiz_micro/rete/socketserver/AbstractBasicGetSocketServer.py +35 -0
- modulitiz_micro/rete/socketserver/AbstractSocketServer.py +267 -0
- modulitiz_micro/rete/ssl/ModuloSsl.py +56 -0
- modulitiz_micro/sistema/EnvVarsEnum.py +9 -0
- modulitiz_micro/sistema/ModuloEnvVars.py +34 -0
- modulitiz_micro/sistema/ModuloSystem.py +298 -0
- modulitiz_micro/sistema/ModuloSystemPipe.py +67 -0
- modulitiz_micro/social/telegram/ModuloTelegram.py +52 -0
- modulitiz_micro/social/telegram/ModuloTelegramSimple.py +26 -0
- modulitiz_micro/util/beans/conf/AbstractBasicConfBean.py +11 -0
- modulitiz_micro/util/beans/conf/AbstractConfBean.py +16 -0
- modulitiz_micro/util/beans/fileconf/AbstractBasicFileConfBean.py +11 -0
- modulitiz_micro/util/beans/fileconf/AbstractFileConfBean.py +13 -0
- modulitiz_micro/util/beans/globalvar/AbstractBasicGlobalVarBean.py +15 -0
- modulitiz_micro/util/beans/globalvar/AbstractGlobalVarBean.py +34 -0
- modulitiz_micro/util/decorators/noAwait.py +23 -0
- modulitiz_micro/util/pip/AbstractModuloPip.py +41 -0
- modulitiz_micro/util/pip/ModuloPip.py +49 -0
- modulitiz_micro/util/scheduler/AbstractScheduler.py +32 -0
- modulitiz_micro/util/spooler/AbstractSpooler.py +14 -0
- modulitiz_micro/util/spooler/Spooler.py +18 -0
- modulitiz_micro/util/spooler/beans/QueueBean.py +8 -0
- modulitiz_micro/util/spooler/decorators/spooler.py +49 -0
- modulitiz_micro/util/spooler/eccezioni/EccezioneSpooler.py +7 -0
- modulitiz_micro/util/spooler/eccezioni/EccezioneSpoolerFull.py +7 -0
- modulitiz_micro/util/unittesting/AbstractOverrideTestUtil.py +18 -0
- modulitiz_micro/util/unittesting/AbstractTestUtil.py +11 -0
- modulitiz_micro/util/unittesting/ModuloRunUnitTest.py +25 -0
- modulitiz_micro/util/wheel/ModuloBuildWheel.py +118 -0
- modulitiz_micro/util/wheel/ModuloToml.py +40 -0
- modulitiz_micro/util/wheel/ModuloWheel.py +12 -0
- modulitiz_micro-2.26.0.dist-info/LICENSE +21 -0
- modulitiz_micro-2.26.0.dist-info/METADATA +63 -0
- modulitiz_micro-2.26.0.dist-info/RECORD +100 -0
- modulitiz_micro-2.26.0.dist-info/WHEEL +5 -0
- modulitiz_micro-2.26.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
import base64
|
2
|
+
|
3
|
+
from modulitiz_micro.ModuloStringhe import ModuloStringhe
|
4
|
+
|
5
|
+
|
6
|
+
class ModuloBase64(object):
|
7
|
+
"""
|
8
|
+
Utility di gestione del sistema di codifica base64.
|
9
|
+
"""
|
10
|
+
|
11
|
+
@staticmethod
|
12
|
+
def codificaFile(inputFile:str,outputFile:str):
|
13
|
+
"""
|
14
|
+
Legge un file binario e scrive un file con il relativo contenuto codificato.
|
15
|
+
"""
|
16
|
+
# leggo
|
17
|
+
with open(inputFile,"rb") as fp:
|
18
|
+
contenuto=fp.read()
|
19
|
+
# codifico
|
20
|
+
encoded=base64.b64encode(contenuto)
|
21
|
+
# scrivo
|
22
|
+
with open(outputFile,"w+b") as fp:
|
23
|
+
fp.write(encoded)
|
24
|
+
@staticmethod
|
25
|
+
def codificaStr(decodedStr:str)->str:
|
26
|
+
"""
|
27
|
+
Converte una stringa.
|
28
|
+
"""
|
29
|
+
return base64.b64encode(decodedStr.encode(ModuloStringhe.CODIFICA_UTF8)).decode(ModuloStringhe.CODIFICA_UTF8)
|
30
|
+
@staticmethod
|
31
|
+
def codificaStrUrlSafe(decodedStr:str)->str:
|
32
|
+
"""
|
33
|
+
Converte una stringa in modo che possa essere usata come url.
|
34
|
+
"""
|
35
|
+
return base64.urlsafe_b64encode(decodedStr.encode(ModuloStringhe.CODIFICA_UTF8)).decode(ModuloStringhe.CODIFICA_UTF8)
|
36
|
+
|
37
|
+
@staticmethod
|
38
|
+
def decodificaFile(inputFile:str,outputFile:str):
|
39
|
+
"""
|
40
|
+
Legge il contenuto codificato di un file e lo decodifica, scrivendo l'output in un altro file.
|
41
|
+
"""
|
42
|
+
# leggo
|
43
|
+
with open(inputFile,"rb") as fp:
|
44
|
+
contenuto=fp.read()
|
45
|
+
# decodifico
|
46
|
+
decoded=base64.b64decode(contenuto)
|
47
|
+
# scrivo
|
48
|
+
with open(outputFile,"w+b") as fp:
|
49
|
+
fp.write(decoded)
|
50
|
+
@staticmethod
|
51
|
+
def decodificaStr(codedStr:str)->str:
|
52
|
+
"""
|
53
|
+
Decodifica una stringa.
|
54
|
+
"""
|
55
|
+
return base64.b64decode(codedStr.encode(ModuloStringhe.CODIFICA_UTF8)).decode(ModuloStringhe.CODIFICA_UTF8)
|
56
|
+
@staticmethod
|
57
|
+
def decodificaStrUrlSafe(codedStr:str)->str:
|
58
|
+
"""
|
59
|
+
Decodifica una stringa che è stata codificata per essere usata come url.
|
60
|
+
"""
|
61
|
+
return base64.urlsafe_b64decode(codedStr.encode(ModuloStringhe.CODIFICA_UTF8)).decode(ModuloStringhe.CODIFICA_UTF8)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import colorama
|
2
|
+
import webcolors
|
3
|
+
|
4
|
+
from modulitiz_micro.rete.http.ModuloHttpUtils import ModuloHttpUtils
|
5
|
+
|
6
|
+
|
7
|
+
class ModuloColorText(object):
|
8
|
+
"""
|
9
|
+
Utility per gestire i colori e stampare a schermo testo colorato.
|
10
|
+
"""
|
11
|
+
|
12
|
+
DEFAULT= '\033[0m'
|
13
|
+
GRASSETTO= DEFAULT+'\033[1m'
|
14
|
+
NERO= '\033[90m'
|
15
|
+
ROSSO= '\033[91m'
|
16
|
+
VERDE= '\033[92m'
|
17
|
+
GIALLO= '\033[93m'
|
18
|
+
BLU= '\033[94m'
|
19
|
+
FUCSIA= '\033[95m'
|
20
|
+
AZZURRO= '\033[96m'
|
21
|
+
|
22
|
+
def __init__(self):
|
23
|
+
colorama.init()
|
24
|
+
|
25
|
+
@staticmethod
|
26
|
+
def wordToRGB(word:str,lang:str="en")->str|None:
|
27
|
+
"""
|
28
|
+
Traduce un colore in formato RGB, è possibile scegliere la lingua di origine.
|
29
|
+
"""
|
30
|
+
if lang!="en":
|
31
|
+
word=ModuloHttpUtils.translate(lang,"en",word)
|
32
|
+
if word is None:
|
33
|
+
return None
|
34
|
+
word=word.replace(" ","").replace("ish","")
|
35
|
+
return webcolors.name_to_hex(word)
|
@@ -0,0 +1,295 @@
|
|
1
|
+
import time
|
2
|
+
from datetime import UTC
|
3
|
+
from datetime import date
|
4
|
+
from datetime import datetime
|
5
|
+
from datetime import time as dt_time
|
6
|
+
from datetime import timedelta
|
7
|
+
from datetime import timezone
|
8
|
+
|
9
|
+
|
10
|
+
class ModuloDate(object):
|
11
|
+
"""
|
12
|
+
Utility per gestire operazioni e formattazioni sulle date.
|
13
|
+
"""
|
14
|
+
|
15
|
+
FORMATO_DATA="%Y-%m-%d"
|
16
|
+
FORMATO_DATA_IT="%d/%m/%Y"
|
17
|
+
FORMATO_DATA_ORA="%Y-%m-%d %H:%M:%S"
|
18
|
+
FORMATO_DATA_ORA_NOMEFILE="%Y-%m-%d_%H-%M-%S"
|
19
|
+
FORMATO_DATA_ORA_NOSPAZI="%Y%m%d%H%M%S"
|
20
|
+
FORMATO_ORA="%H:%M:%S"
|
21
|
+
|
22
|
+
|
23
|
+
@staticmethod
|
24
|
+
def now()->datetime:
|
25
|
+
"""
|
26
|
+
Data e ora attuali.
|
27
|
+
"""
|
28
|
+
return datetime.now()
|
29
|
+
|
30
|
+
@classmethod
|
31
|
+
def nowUtc(cls)->datetime:
|
32
|
+
"""
|
33
|
+
Data e ora attuali in formato UTC (quindi senza fuso orario e DST)
|
34
|
+
"""
|
35
|
+
data=datetime.now(timezone.utc)
|
36
|
+
data=cls.setTimezoneUtc(data)
|
37
|
+
return data
|
38
|
+
|
39
|
+
@staticmethod
|
40
|
+
def today()->date:
|
41
|
+
"""
|
42
|
+
Data odierna, senza ora.
|
43
|
+
"""
|
44
|
+
return date.today()
|
45
|
+
|
46
|
+
@staticmethod
|
47
|
+
def getSecs()->int:
|
48
|
+
"""
|
49
|
+
Timestamp in secondi in formato UTC
|
50
|
+
"""
|
51
|
+
return int(time.time())
|
52
|
+
|
53
|
+
@staticmethod
|
54
|
+
def getMillis()->int:
|
55
|
+
"""
|
56
|
+
Timestamp in millisecondi in formato UTC
|
57
|
+
"""
|
58
|
+
return int(time.time()*1000)
|
59
|
+
|
60
|
+
@classmethod
|
61
|
+
def getWeekDay(cls,data:datetime|None=None)->str:
|
62
|
+
"""
|
63
|
+
Se te lo restituisce in inglese devi settare il locale
|
64
|
+
"""
|
65
|
+
if data is None:
|
66
|
+
data=cls.now()
|
67
|
+
return data.date().strftime("%A")
|
68
|
+
|
69
|
+
#
|
70
|
+
# conversioni
|
71
|
+
#
|
72
|
+
@classmethod
|
73
|
+
def dateToString(cls,data:datetime|None=None,formato:str=FORMATO_DATA_ORA)->str:
|
74
|
+
"""
|
75
|
+
Formatta un oggetto data.
|
76
|
+
:param data: data da formattare, se non specificata viene usata la data attuale
|
77
|
+
:param formato: in che modo deve essere formattata la data, se non specificato viene usato il formato inglese
|
78
|
+
"""
|
79
|
+
if data is None:
|
80
|
+
data=cls.now()
|
81
|
+
return data.strftime(formato)
|
82
|
+
|
83
|
+
@staticmethod
|
84
|
+
def stringToDate(stringa:str,formato:str=FORMATO_DATA_ORA)->datetime:
|
85
|
+
"""
|
86
|
+
Trasforma una data in formato stringa a oggetto.
|
87
|
+
:param stringa: stringa da trasformare in data
|
88
|
+
:param formato: in che modo deve essere formattata la data, se non specificato viene usato il formato inglese
|
89
|
+
"""
|
90
|
+
return datetime.strptime(stringa,formato)
|
91
|
+
|
92
|
+
@staticmethod
|
93
|
+
def timeToString(orario:dt_time,formato:str=FORMATO_ORA)->str:
|
94
|
+
"""
|
95
|
+
Formatta un oggetto di tipo ora.
|
96
|
+
:param orario: orario da formattare
|
97
|
+
:param formato: in che modo deve essere formattato l'orario, se non specificato viene usato il formato standard
|
98
|
+
"""
|
99
|
+
return orario.strftime(formato)
|
100
|
+
@classmethod
|
101
|
+
def stringToTime(cls,stringa:str,formato:str=FORMATO_ORA)->dt_time:
|
102
|
+
"""
|
103
|
+
Formatta un oggetto di tipo ora.
|
104
|
+
:param stringa: stringa da formattare in orario
|
105
|
+
:param formato: in che modo deve essere formattato l'orario, se non specificato viene usato il formato standard
|
106
|
+
"""
|
107
|
+
return cls.dateToTime(cls.stringToDate(stringa,formato))
|
108
|
+
|
109
|
+
@classmethod
|
110
|
+
def timeToDate(cls,orario:dt_time)->datetime:
|
111
|
+
"""
|
112
|
+
Converte da oggetto orario a data completa.
|
113
|
+
Viene aggiunta la data odierna all'orario passato in input.
|
114
|
+
"""
|
115
|
+
return datetime.combine(cls.today(), orario)
|
116
|
+
|
117
|
+
@staticmethod
|
118
|
+
def timedeltaToTime(orario:timedelta)->dt_time:
|
119
|
+
"""
|
120
|
+
Converte un oggetto timedelta a oggetto orario.
|
121
|
+
"""
|
122
|
+
return (datetime.min + orario).time()
|
123
|
+
|
124
|
+
@staticmethod
|
125
|
+
def dateToTime(data:datetime)->dt_time:
|
126
|
+
"""
|
127
|
+
Rimuove la data da un oggetto data completo, lasciando solo l'orario.
|
128
|
+
"""
|
129
|
+
return data.time()
|
130
|
+
|
131
|
+
@staticmethod
|
132
|
+
def dateToTimestamp(data:datetime)->int:
|
133
|
+
"""
|
134
|
+
Converte un oggetto data completo in timestamp in secondi.
|
135
|
+
Se ti serve avere il timestamp in formato UTC usa il metodo dedicato.
|
136
|
+
"""
|
137
|
+
return int(datetime.timestamp(data))
|
138
|
+
@staticmethod
|
139
|
+
def timestampToDate(timestamp:int|float)->datetime:
|
140
|
+
"""
|
141
|
+
Converte un timestamp in secondi in un oggetto data completo.
|
142
|
+
Se ti serve avere il timestamp in formato UTC usa il metodo dedicato.
|
143
|
+
"""
|
144
|
+
return datetime.fromtimestamp(timestamp)
|
145
|
+
|
146
|
+
@classmethod
|
147
|
+
def dateToTimestampUtc(cls,data:datetime)->int:
|
148
|
+
"""
|
149
|
+
Converte un oggetto data completo in timestamp in secondi in formato UTC.
|
150
|
+
"""
|
151
|
+
return cls.dateToTimestamp(cls.setTimezoneUtc(data))
|
152
|
+
@classmethod
|
153
|
+
def timestampUtcToDate(cls,timestamp:int|float)->datetime:
|
154
|
+
"""
|
155
|
+
Converte un timestamp in secondi in formato UTC in un oggetto data completo.
|
156
|
+
Questo metodo richiede python >= 3.11
|
157
|
+
"""
|
158
|
+
return datetime.fromtimestamp(timestamp,UTC)
|
159
|
+
|
160
|
+
#
|
161
|
+
# operazioni
|
162
|
+
#
|
163
|
+
@staticmethod
|
164
|
+
def dateDiff(data1:datetime,data2:datetime)->timedelta:
|
165
|
+
"""
|
166
|
+
Calcola la differenza di tempo (sia data che oraria) tra 2 date complete.
|
167
|
+
"""
|
168
|
+
return data1-data2
|
169
|
+
|
170
|
+
@classmethod
|
171
|
+
def minutesDiff(cls,data1:datetime,data2:datetime)->int:
|
172
|
+
"""
|
173
|
+
Calcola la differenza in minuti tra 2 date complete.
|
174
|
+
"""
|
175
|
+
diff=cls.dateDiff(data1,data2)
|
176
|
+
diffValue=0
|
177
|
+
if diff.days is not None and diff.days!=0:
|
178
|
+
diffValue+=diff.days*24*60
|
179
|
+
diffValue+=int(diff.seconds/60)
|
180
|
+
return diffValue
|
181
|
+
@classmethod
|
182
|
+
def hoursDiff(cls,data1:datetime,data2:datetime)->int:
|
183
|
+
"""
|
184
|
+
Calcola la differenza in ore tra 2 date complete.
|
185
|
+
"""
|
186
|
+
diff=cls.dateDiff(data1, data2)
|
187
|
+
diffValue=0
|
188
|
+
if diff.days is not None and diff.days!=0:
|
189
|
+
diffValue+=diff.days*24
|
190
|
+
diffValue+=int(diff.seconds/3600)
|
191
|
+
return diffValue
|
192
|
+
@classmethod
|
193
|
+
def daysDiff(cls,data1:datetime,data2:datetime) -> int:
|
194
|
+
"""
|
195
|
+
Calcola la differenza in giorni tra 2 date complete.
|
196
|
+
"""
|
197
|
+
diff=cls.dateDiff(data1,data2)
|
198
|
+
if diff.days is not None and diff.days!=0:
|
199
|
+
return diff.days
|
200
|
+
return 0
|
201
|
+
|
202
|
+
@staticmethod
|
203
|
+
def plusMinusDays(data:datetime,days:int|float)->datetime:
|
204
|
+
"""
|
205
|
+
Aggiunge o toglie giorni ad una data completa.
|
206
|
+
"""
|
207
|
+
td=timedelta(days=abs(days))
|
208
|
+
if days>=0:
|
209
|
+
return data + td
|
210
|
+
return data - td
|
211
|
+
|
212
|
+
@staticmethod
|
213
|
+
def plusMinusHours(data:datetime,hours:int|float)->datetime:
|
214
|
+
"""
|
215
|
+
Aggiunge o toglie ore ad una data completa.
|
216
|
+
"""
|
217
|
+
td=timedelta(hours=abs(hours))
|
218
|
+
if hours>=0:
|
219
|
+
return data + td
|
220
|
+
return data - td
|
221
|
+
|
222
|
+
@staticmethod
|
223
|
+
def plusMinusMinutes(data:datetime,minutes:int|float)->datetime:
|
224
|
+
"""
|
225
|
+
Aggiunge o toglie minuti ad una data completa.
|
226
|
+
"""
|
227
|
+
td=timedelta(minutes=abs(minutes))
|
228
|
+
if minutes>=0:
|
229
|
+
return data + td
|
230
|
+
return data - td
|
231
|
+
|
232
|
+
@staticmethod
|
233
|
+
def plusMinusSeconds(data:datetime,seconds:int|float)->datetime:
|
234
|
+
"""
|
235
|
+
Aggiunge o toglie minuti ad una data completa.
|
236
|
+
"""
|
237
|
+
td=timedelta(seconds=abs(seconds))
|
238
|
+
if seconds>=0:
|
239
|
+
return data + td
|
240
|
+
return data - td
|
241
|
+
|
242
|
+
@staticmethod
|
243
|
+
def setStartOfDay(data:datetime)->datetime:
|
244
|
+
"""
|
245
|
+
Imposta l'inizio del giorno ad una data completa.
|
246
|
+
"""
|
247
|
+
return data.replace(hour=0, minute=0, second=0, microsecond=0)
|
248
|
+
|
249
|
+
@staticmethod
|
250
|
+
def setEndOfDay(data:datetime)->datetime:
|
251
|
+
"""
|
252
|
+
Imposta la fine del giorno ad una data completa.
|
253
|
+
"""
|
254
|
+
return data.replace(hour=23, minute=59, second=59, microsecond=999999)
|
255
|
+
|
256
|
+
@classmethod
|
257
|
+
def setTimezoneLocale(cls,data:datetime)->datetime:
|
258
|
+
"""
|
259
|
+
Imposta il fuso orario locale ad una data completa.
|
260
|
+
"""
|
261
|
+
return cls.setTimezoneUtc(data).astimezone(tz=None)
|
262
|
+
|
263
|
+
@classmethod
|
264
|
+
def setTimezoneUtc(cls,data:datetime)->datetime:
|
265
|
+
"""
|
266
|
+
Imposta SOLO il fuso orario UTC ad una data completa.
|
267
|
+
"""
|
268
|
+
return cls.setTimezoneFromTzInfo(data,timezone.utc)
|
269
|
+
|
270
|
+
@staticmethod
|
271
|
+
def setTimezoneFromTzInfo(data:datetime,tz:datetime.tzinfo)->datetime:
|
272
|
+
"""
|
273
|
+
Imposta un fuso orario ad una data completa.
|
274
|
+
"""
|
275
|
+
return data.replace(tzinfo=tz)
|
276
|
+
|
277
|
+
@classmethod
|
278
|
+
def getTimezoneLocal(cls)->datetime.tzinfo:
|
279
|
+
"""
|
280
|
+
Ritorna il fuso orario locale.
|
281
|
+
"""
|
282
|
+
return cls.now().astimezone().tzinfo
|
283
|
+
|
284
|
+
#
|
285
|
+
# altre funzioni
|
286
|
+
#
|
287
|
+
@classmethod
|
288
|
+
def calculateElapsedSecs(cls,millisInizio:int)->str:
|
289
|
+
"""
|
290
|
+
Crea la frase che mostra quanti secondi sono trascorsi dall'inizio.
|
291
|
+
"""
|
292
|
+
elapsedSecs=int((cls.getMillis()-millisInizio)*0.001)
|
293
|
+
if elapsedSecs==0:
|
294
|
+
return ""
|
295
|
+
return f" in {elapsedSecs}s"
|
@@ -0,0 +1,58 @@
|
|
1
|
+
import random
|
2
|
+
import sys
|
3
|
+
|
4
|
+
|
5
|
+
class ModuloFunzioni(object):
|
6
|
+
"""
|
7
|
+
Utility riguardanti le funzioni o non catalogabili in modo definito.
|
8
|
+
"""
|
9
|
+
|
10
|
+
GENERI={'m':'Maschio','f':'Femmina'}
|
11
|
+
|
12
|
+
@staticmethod
|
13
|
+
def getFunctionName(n:int=0)->str:
|
14
|
+
"""
|
15
|
+
Per il nome della funzione corrente, non impostare nessun parametro o impostare 0;
|
16
|
+
Per il nome della funzione chiamante, impostare 1;
|
17
|
+
Per il nome della funzione chiamante la funzione, impostare 2;
|
18
|
+
E via dicendo così.
|
19
|
+
"""
|
20
|
+
return sys._getframe(n + 1).f_code.co_name
|
21
|
+
|
22
|
+
@staticmethod
|
23
|
+
def getFullyQualifiedName(funzione)->str:
|
24
|
+
"""
|
25
|
+
Ritorna il package + il nome della funzione;
|
26
|
+
in questo modo è possibile distinguere 2 funzioni con lo stesso nome, ad esempio:
|
27
|
+
src.funzione
|
28
|
+
src.package.funzione
|
29
|
+
src.package.modulo.funzione
|
30
|
+
src.package.modulo.classe.funzione
|
31
|
+
"""
|
32
|
+
return funzione.__module__+"."+funzione.__qualname__
|
33
|
+
|
34
|
+
@staticmethod
|
35
|
+
def orderDict(diz:dict)->dict:
|
36
|
+
"""
|
37
|
+
Ordina gli elementi di un dizionario.
|
38
|
+
Nota: ha senso solo se hai intenzione di esporlo all'utente sotto forma di lista.
|
39
|
+
"""
|
40
|
+
myKeys = list(diz.keys())
|
41
|
+
myKeys.sort()
|
42
|
+
newDiz = {i: diz[i] for i in myKeys}
|
43
|
+
return newDiz
|
44
|
+
|
45
|
+
@staticmethod
|
46
|
+
def dictGetFirstValue(diz: dict):
|
47
|
+
"""
|
48
|
+
Ritorna il valore del primo elemnto di un dizionario.
|
49
|
+
È ottimizzato per oggetti con molti elementi.
|
50
|
+
"""
|
51
|
+
return next(iter(diz.items()))[1]
|
52
|
+
|
53
|
+
@staticmethod
|
54
|
+
def randomBoolean()->bool:
|
55
|
+
"""
|
56
|
+
Genera un valore booleano in modo randomico.
|
57
|
+
"""
|
58
|
+
return bool(random.getrandbits(1))
|
@@ -0,0 +1,150 @@
|
|
1
|
+
import re
|
2
|
+
|
3
|
+
from modulitiz_micro.ModuloStringhe import ModuloStringhe
|
4
|
+
|
5
|
+
|
6
|
+
class ModuloListe(object):
|
7
|
+
"""
|
8
|
+
Utility di gestione degli oggetti liste.
|
9
|
+
"""
|
10
|
+
|
11
|
+
@staticmethod
|
12
|
+
def mergeListsOfDicts(listaFrom: list[dict],keyFrom: str|int,listaTo: list[dict],keyTo: str|int) -> list[dict]:
|
13
|
+
"""
|
14
|
+
Esempio: queste due liste...
|
15
|
+
[
|
16
|
+
{'index':1},
|
17
|
+
{'index':3}
|
18
|
+
]
|
19
|
+
|
20
|
+
[
|
21
|
+
{'id':1,'val':'a'},
|
22
|
+
{'id':2,'val':'b'},
|
23
|
+
{'id':3,'val':'c'},
|
24
|
+
{'id':4,'val':'d'}
|
25
|
+
]
|
26
|
+
|
27
|
+
... diventano così
|
28
|
+
|
29
|
+
[
|
30
|
+
{'id':1,'val':'a'},
|
31
|
+
{'id':3,'val':'c'}
|
32
|
+
]
|
33
|
+
"""
|
34
|
+
nuovaLista=[]
|
35
|
+
for elemFrom in listaFrom:
|
36
|
+
valore=str(elemFrom[keyFrom])
|
37
|
+
for elemTo in listaTo:
|
38
|
+
if str(elemTo[keyTo])==valore:
|
39
|
+
nuovaLista.append(elemTo)
|
40
|
+
return nuovaLista
|
41
|
+
|
42
|
+
@classmethod
|
43
|
+
def humanOrder(cls,lista: list) -> list:
|
44
|
+
"""
|
45
|
+
Ordina una lista in modo che sia più leggibile: ad esempio:
|
46
|
+
[elemento1,elemento10,elemento2]
|
47
|
+
viene ordinato in questo modo:
|
48
|
+
[elemento1,elemento2,elemento10]
|
49
|
+
invece che:
|
50
|
+
[elemento10,elemento1,elemento2]
|
51
|
+
"""
|
52
|
+
convert=lambda text:int(text) if text.isdigit() else text
|
53
|
+
alphanum=lambda key:[convert(c) for c in re.split(r'(\d+)',key)]
|
54
|
+
return sorted(lista,key=alphanum)
|
55
|
+
|
56
|
+
@staticmethod
|
57
|
+
def eliminaElementi(lista: list,elemsToRemove: list|tuple) -> list:
|
58
|
+
"""
|
59
|
+
Elimina dalla lista gli elementi specificati.
|
60
|
+
"""
|
61
|
+
for elemToRemove in elemsToRemove:
|
62
|
+
while elemToRemove in lista:
|
63
|
+
lista.remove(elemToRemove)
|
64
|
+
return lista
|
65
|
+
|
66
|
+
@classmethod
|
67
|
+
def eliminaElementiVuoti(cls,lista: list) -> list:
|
68
|
+
"""
|
69
|
+
Elimina dalla lista le stringhe vuote e gli elementi null
|
70
|
+
"""
|
71
|
+
return cls.eliminaElementi(lista,(None,""))
|
72
|
+
|
73
|
+
@staticmethod
|
74
|
+
def diff(lista1: list,lista2: list) -> tuple:
|
75
|
+
"""
|
76
|
+
Calcola la differenza tra 2 liste, mostra gli elementi che mancano dalla 1a alla 2a e viceversa.
|
77
|
+
"""
|
78
|
+
set1=set(lista1)
|
79
|
+
set2=set(lista2)
|
80
|
+
toAdd=list(set1-set2)
|
81
|
+
toRemove=list(set2-set1)
|
82
|
+
return toAdd,toRemove
|
83
|
+
|
84
|
+
@staticmethod
|
85
|
+
def affianca(lista1: list,lista2: list) -> list:
|
86
|
+
"""
|
87
|
+
Unisce 2 liste.
|
88
|
+
"""
|
89
|
+
return list(zip(lista1,lista2))
|
90
|
+
|
91
|
+
@staticmethod
|
92
|
+
def separa(lista: list) -> list:
|
93
|
+
"""
|
94
|
+
Separa 2 liste.
|
95
|
+
"""
|
96
|
+
return [list(x) for x in zip(*lista)]
|
97
|
+
|
98
|
+
@staticmethod
|
99
|
+
def chunks(lista: list,n: int):
|
100
|
+
"""
|
101
|
+
Divide una lista in una lista di liste.
|
102
|
+
"""
|
103
|
+
for i in range(0,len(lista),n):
|
104
|
+
yield lista[i:i+n]
|
105
|
+
|
106
|
+
@staticmethod
|
107
|
+
def isEmpty(lista: list) -> bool:
|
108
|
+
"""
|
109
|
+
Verifica se una lista è null o vuota.
|
110
|
+
"""
|
111
|
+
return lista is None or lista==[]
|
112
|
+
|
113
|
+
@staticmethod
|
114
|
+
def collectionContainsString(lista: list|tuple,testo: str) -> bool:
|
115
|
+
"""
|
116
|
+
Verifica se almeno un elemento di una lista o una tupla contiene una stringa.
|
117
|
+
"""
|
118
|
+
for elem in lista:
|
119
|
+
if ModuloStringhe.contains(elem,testo):
|
120
|
+
return True
|
121
|
+
return False
|
122
|
+
|
123
|
+
@staticmethod
|
124
|
+
def stringContainsCollection(testo: str,lista: list|tuple) -> bool:
|
125
|
+
"""
|
126
|
+
Verifica se una stringa contiene almeno un elemento di una lista o una tupla.
|
127
|
+
"""
|
128
|
+
for elem in lista:
|
129
|
+
if ModuloStringhe.contains(testo,elem):
|
130
|
+
return True
|
131
|
+
return False
|
132
|
+
|
133
|
+
@staticmethod
|
134
|
+
def collectionSafeGet(collection: dict|list|tuple,*keys):
|
135
|
+
"""
|
136
|
+
Ritorna elementi innestati in un dizionario, lista o tupla in una sola volta.
|
137
|
+
Se un elemento intermedio non esiste ritorna null.
|
138
|
+
Ad esempio:
|
139
|
+
'ciao' = funzione(
|
140
|
+
{'a':[('ciao',),]}
|
141
|
+
,
|
142
|
+
'a',0,0
|
143
|
+
)
|
144
|
+
"""
|
145
|
+
for key in keys:
|
146
|
+
try:
|
147
|
+
collection=collection[key]
|
148
|
+
except (IndexError,KeyError):
|
149
|
+
return
|
150
|
+
return collection
|
@@ -0,0 +1,72 @@
|
|
1
|
+
import json
|
2
|
+
|
3
|
+
from modulitiz_micro.ModuloDate import ModuloDate
|
4
|
+
from modulitiz_micro.ModuloListe import ModuloListe
|
5
|
+
from modulitiz_micro.eccezioni.http.EccezioneHttpGeneric import EccezioneHttpGeneric
|
6
|
+
from modulitiz_micro.files import ModuloLogging
|
7
|
+
from modulitiz_micro.rete.http.ModuloHttp import ModuloHttp
|
8
|
+
from modulitiz_micro.rete.http.ModuloHttpUtils import ModuloHttpUtils
|
9
|
+
|
10
|
+
|
11
|
+
class ModuloMeteo(object):
|
12
|
+
"""
|
13
|
+
Utility di gestione delle previsioni meteo.
|
14
|
+
"""
|
15
|
+
OPZIONI="lang=it&units=metric"
|
16
|
+
KEY="appid=e28cd365c35c12e3ed8f2d84e04398c9"
|
17
|
+
|
18
|
+
__URL_BASE="https://api.openweathermap.org"
|
19
|
+
URL_ATTUALE=__URL_BASE+f"/data/2.5/weather?{OPZIONI}&{KEY}&q="
|
20
|
+
URL_PREVISIONE=__URL_BASE+f"/data/2.5/forecast?{OPZIONI}&{KEY}&q="
|
21
|
+
|
22
|
+
def __init__(self,logger:ModuloLogging):
|
23
|
+
self.__logger=logger
|
24
|
+
|
25
|
+
def getPrevisionePioggiaFinoADomani(self,citta:str,codStato:str)->list|None:
|
26
|
+
"""
|
27
|
+
Chiede le previsioni fino al giorno dopo e mostra solo i risultati che dicono che pioverà.
|
28
|
+
"""
|
29
|
+
adesso=ModuloDate.now()
|
30
|
+
domani=ModuloDate.setEndOfDay(ModuloDate.plusMinusDays(adesso,1))
|
31
|
+
oreDiff=ModuloDate.hoursDiff(domani, adesso)
|
32
|
+
elementi=self.__getPrevisioni(citta, codStato,True,None,oreDiff)
|
33
|
+
if elementi is None:
|
34
|
+
return None
|
35
|
+
# filtro gli elementi
|
36
|
+
lista=[]
|
37
|
+
for elem in elementi:
|
38
|
+
if ModuloListe.collectionSafeGet(elem,'rain') is not None:
|
39
|
+
lista.append(elem)
|
40
|
+
return lista
|
41
|
+
|
42
|
+
def __getPrevisioni(self,citta:str,codStato:str,includiPrimaPrevisione:bool,stepHours:int|None,maxHours:int)->list|None:
|
43
|
+
cittaEStato=citta+","+codStato
|
44
|
+
url=self.URL_PREVISIONE+ModuloHttpUtils.encodeUrl(cittaEStato)
|
45
|
+
http=ModuloHttp(url,self.__logger,False)
|
46
|
+
try:
|
47
|
+
response=http.doGet(0,False)
|
48
|
+
except EccezioneHttpGeneric:
|
49
|
+
return None
|
50
|
+
responseObj=json.loads(response.responseBody)
|
51
|
+
lista=responseObj['list']
|
52
|
+
maxLista=len(lista)
|
53
|
+
# calcolo gli indici
|
54
|
+
if maxHours is not None:
|
55
|
+
maxInd=int(maxHours/3)+1
|
56
|
+
if maxInd>=maxLista:
|
57
|
+
maxInd=maxLista-1
|
58
|
+
else:
|
59
|
+
maxInd=maxLista-1
|
60
|
+
if stepHours is None:
|
61
|
+
step=1
|
62
|
+
else:
|
63
|
+
step=int(stepHours/3)
|
64
|
+
inds=list(range(4,maxInd,step))
|
65
|
+
if includiPrimaPrevisione:
|
66
|
+
inds.insert(0,1)
|
67
|
+
# processo il json
|
68
|
+
output=[]
|
69
|
+
for ind in inds:
|
70
|
+
elem=lista[ind]
|
71
|
+
output.append(elem)
|
72
|
+
return output
|