modulitiz-micro 3.0.0__py314-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 (98) hide show
  1. modulitiz_micro/SerialModule.py +55 -0
  2. modulitiz_micro/SunUtil.py +22 -0
  3. modulitiz_micro/database/ModuloSqlOracle.py +19 -0
  4. modulitiz_micro/database/ModuloSqlServer.py +43 -0
  5. modulitiz_micro/database/exceptions/ExceptionDbNoData.py +7 -0
  6. modulitiz_micro/database/mysql/AbstractBasicMysql.py +112 -0
  7. modulitiz_micro/database/mysql/ModuloMysql.py +157 -0
  8. modulitiz_micro/database/mysql/MysqlCommonConverter.py +55 -0
  9. modulitiz_micro/database/mysql/exceptions/ExceptionMysqlOffline.py +6 -0
  10. modulitiz_micro/dom/DomModule.py +48 -0
  11. modulitiz_micro/exceptions/ExceptionCtrlC.py +7 -0
  12. modulitiz_micro/exceptions/ExceptionScheduler.py +7 -0
  13. modulitiz_micro/exceptions/http/ExceptionHttp.py +8 -0
  14. modulitiz_micro/exceptions/http/ExceptionHttp404.py +7 -0
  15. modulitiz_micro/exceptions/http/ExceptionHttpGeneric.py +7 -0
  16. modulitiz_micro/exceptions/http/ExceptionHttpRetriesExceeded.py +7 -0
  17. modulitiz_micro/files/cache/decorators/cacheRam.py +26 -0
  18. modulitiz_micro/files/git/ModuloGit.py +32 -0
  19. modulitiz_micro/files/git/decorators/catchAndRaiseGitExceptions.py +19 -0
  20. modulitiz_micro/files/git/exceptions/ExceptionGit.py +7 -0
  21. modulitiz_micro/iot/ModuleIotDevice.py +61 -0
  22. modulitiz_micro/iot/beans/IotDeviceBean.py +13 -0
  23. modulitiz_micro/iot/enums/IotOSEnum.py +12 -0
  24. modulitiz_micro/iot/espurna/ModuleEspurna.py +3 -0
  25. modulitiz_micro/keylogger/ExceptionKeyLogger.py +7 -0
  26. modulitiz_micro/keylogger/ModuloKeylogger.py +73 -0
  27. modulitiz_micro/rete/ModuleAndroidTVRemote.py +115 -0
  28. modulitiz_micro/rete/ModuloNetworking.py +71 -0
  29. modulitiz_micro/rete/ModuloOpenVpn.py +15 -0
  30. modulitiz_micro/rete/email/EmailBean.py +5 -0
  31. modulitiz_micro/rete/email/ModuloEmail.py +88 -0
  32. modulitiz_micro/rete/http/ModuloHttp.py +127 -0
  33. modulitiz_micro/rete/http/ModuloHttpConnectionSafe.py +96 -0
  34. modulitiz_micro/rete/http/ModuloHttpUtils.py +68 -0
  35. modulitiz_micro/rete/http/beans/HttpResponseBean.py +5 -0
  36. modulitiz_micro/rete/http/decorators/catchAndRaiseHttpExceptions.py +28 -0
  37. modulitiz_micro/rete/http/ecovacsdeebot/AbstractModuleEcovacsDeebot.py +94 -0
  38. modulitiz_micro/rete/http/ecovacsdeebot/ModuleEcovacsDeebot.py +43 -0
  39. modulitiz_micro/rete/http/enums/HttpHeaderNameEnum.py +14 -0
  40. modulitiz_micro/rete/http/huawei/fusionsolar/ModuleBasicHuaweiFusionSolar.py +114 -0
  41. modulitiz_micro/rete/http/huawei/fusionsolar/ModuleHuaweiFusionSolar.py +94 -0
  42. modulitiz_micro/rete/http/huawei/fusionsolar/beans/TokenBean.py +28 -0
  43. modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/DeviceBean.py +8 -0
  44. modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/DeviceDataBattery.py +29 -0
  45. modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/DeviceDataPowerSensor.py +49 -0
  46. modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/DeviceDataResidentialInverter.py +46 -0
  47. modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/batteryunitinfo/BatteryUnitInfo.py +11 -0
  48. modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/batteryunitinfo/BatteryUnitInfoUnit.py +9 -0
  49. modulitiz_micro/rete/http/huawei/fusionsolar/enums/BatteryStatusEnum.py +11 -0
  50. modulitiz_micro/rete/http/huawei/fusionsolar/enums/DevTypeIdEnum.py +29 -0
  51. modulitiz_micro/rete/http/huawei/fusionsolar/exceptions/ExceptionTooManyLogins.py +7 -0
  52. modulitiz_micro/rete/http/huawei/fusionsolar/service/AbstractHuaweiFusionSolar.py +77 -0
  53. modulitiz_micro/rete/http/mapbox/AbstractModuleMapBox.py +36 -0
  54. modulitiz_micro/rete/http/mapbox/ModuleMapBox.py +12 -0
  55. modulitiz_micro/rete/http/mapbox/inner/directions/ModuleMapBoxDirections.py +54 -0
  56. modulitiz_micro/rete/http/mapbox/inner/directions/beans/HighTrafficPointBean.py +7 -0
  57. modulitiz_micro/rete/ntp/AbstractModuloNtp.py +95 -0
  58. modulitiz_micro/rete/ntp/ModuloNtpIt.py +8 -0
  59. modulitiz_micro/rete/socketserver/AbstractBasicGetSocketServer.py +35 -0
  60. modulitiz_micro/rete/socketserver/AbstractSocketServer.py +268 -0
  61. modulitiz_micro/rete/ssl/ModuloSsl.py +55 -0
  62. modulitiz_micro/sistema/ModuloEnvVars.py +34 -0
  63. modulitiz_micro/sistema/ModuloSystemPipe.py +67 -0
  64. modulitiz_micro/social/telegram/AbstractModuloTelegram.py +50 -0
  65. modulitiz_micro/social/telegram/ModuloTelegramSimple.py +26 -0
  66. modulitiz_micro/social/telegram/bot/AbstractTelegramBotMainService.py +94 -0
  67. modulitiz_micro/social/telegram/bot/AbstractTelegramBotService.py +47 -0
  68. modulitiz_micro/social/telegram/bot/enums/TelegramBotCommandEnum.py +10 -0
  69. modulitiz_micro/social/telegram/bot/util/TelegramBotUtil.py +7 -0
  70. modulitiz_micro/util/SolarUtil.py +18 -0
  71. modulitiz_micro/util/beans/CoordinatesBean.py +7 -0
  72. modulitiz_micro/util/beans/globalvar/AbstractBasicGlobalVarBean.py +15 -0
  73. modulitiz_micro/util/scheduler/AbstractSchedulerBasicService.py +16 -0
  74. modulitiz_micro/util/scheduler/SchedulerBasicService.py +64 -0
  75. modulitiz_micro/util/scheduler/enums/ExecutorEnum.py +7 -0
  76. modulitiz_micro/util/scheduler/enums/TriggerEnum.py +9 -0
  77. modulitiz_micro/weather/AbstractModuleWeather.py +58 -0
  78. modulitiz_micro/weather/ModuleWeather.py +25 -0
  79. modulitiz_micro/weather/beans/AbstractWeatherBean.py +6 -0
  80. modulitiz_micro/weather/beans/AbstractWeatherDataBean.py +21 -0
  81. modulitiz_micro/weather/beans/commons/WeatherBean.py +11 -0
  82. modulitiz_micro/weather/beans/commons/WeatherCloudsBean.py +6 -0
  83. modulitiz_micro/weather/beans/commons/WeatherMainBean.py +13 -0
  84. modulitiz_micro/weather/beans/commons/WeatherRainBean.py +5 -0
  85. modulitiz_micro/weather/beans/commons/WeatherWindBean.py +8 -0
  86. modulitiz_micro/weather/beans/current/WeatherCurrentDataBean.py +25 -0
  87. modulitiz_micro/weather/beans/current/inners/WeatherSysBean.py +5 -0
  88. modulitiz_micro/weather/beans/forecast/WeatherForecastDataBean.py +12 -0
  89. modulitiz_micro/weather/beans/forecast/inners/WeatherCityBean.py +13 -0
  90. modulitiz_micro/weather/beans/forecast/inners/WeatherForecastBean.py +31 -0
  91. modulitiz_micro/weather/beans/forecast/inners/WeatherMainForecastBean.py +9 -0
  92. modulitiz_micro/weather/beans/forecast/inners/WeatherSysBean.py +9 -0
  93. modulitiz_micro/weather/enums/IdWeatherEnum.py +68 -0
  94. modulitiz_micro-3.0.0.dist-info/METADATA +62 -0
  95. modulitiz_micro-3.0.0.dist-info/RECORD +98 -0
  96. modulitiz_micro-3.0.0.dist-info/WHEEL +5 -0
  97. modulitiz_micro-3.0.0.dist-info/licenses/LICENSE +21 -0
  98. modulitiz_micro-3.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,55 @@
1
+ import serial
2
+ import serial.tools.list_ports
3
+
4
+ from modulitiz_nano.ModuloColorText import ModuloColorText
5
+ from modulitiz_nano.ModuloDate import ModuloDate
6
+ from modulitiz_nano.sistema.EncodingEnum import EncodingEnum
7
+
8
+
9
+ class SerialModule(object):
10
+ """
11
+ Utility di gestione della connessione seriale / RS232
12
+ """
13
+
14
+ def __init__(self):
15
+ self.conn=None
16
+
17
+ def populate(self,port: str,baudrate: int):
18
+ self.conn=serial.Serial(port,baudrate,timeout=1)
19
+
20
+ @staticmethod
21
+ def findFirstPortConnected()->str|None:
22
+ ports:list|tuple=serial.tools.list_ports.comports()
23
+ if not ports:
24
+ return None
25
+ return min(ports)[0]
26
+
27
+ def isOpen(self)->bool:
28
+ """
29
+ Controlla se la connessione alla porta è aperta.
30
+ """
31
+ return self.conn is not None and self.conn.isOpen()
32
+
33
+ def read(self, exitCallback):
34
+ """
35
+ Reads serial strings and prints it to standard output.
36
+ """
37
+ try:
38
+ while not exitCallback():
39
+ character=self.conn.read(1).decode(EncodingEnum.UTF8,"replace")
40
+ if character!="\n":
41
+ msg=character
42
+ else:
43
+ msg="\n%s%s >>> %s"%(ModuloDate.dateToString(None,ModuloDate.FORMATO_ORA),ModuloColorText.BLU,ModuloColorText.DEFAULT)
44
+ print(msg,end="",flush=True)
45
+ finally:
46
+ self.close()
47
+
48
+ def close(self):
49
+ """
50
+ Chiude la connessione alla porta.
51
+ """
52
+ if not self.isOpen():
53
+ return
54
+ self.conn.close()
55
+ self.conn=None
@@ -0,0 +1,22 @@
1
+ from datetime import datetime
2
+
3
+ from suntime import Sun
4
+
5
+ from modulitiz_nano.ModuloDate import ModuloDate
6
+
7
+
8
+ class SunUtil(object):
9
+ @staticmethod
10
+ def getLocalSunrise(lat: float,long: float,dateTime: datetime|None = None) -> datetime:
11
+ if dateTime is None:
12
+ dateTime=ModuloDate.now()
13
+ sun=Sun(lat,long)
14
+ return ModuloDate.removeTimezoneInfo(sun.get_sunrise_time(dateTime,ModuloDate.getTimezoneLocal(dateTime)))
15
+
16
+ @staticmethod
17
+ def getLocalSunset(lat: float,long: float,dateTime: datetime|None = None) -> datetime:
18
+ if dateTime is None:
19
+ dateTime=ModuloDate.now()
20
+ dateTime=ModuloDate.plusMinusDays(dateTime,1)
21
+ sun=Sun(lat,long)
22
+ return ModuloDate.removeTimezoneInfo(sun.get_sunset_time(dateTime,ModuloDate.getTimezoneLocal(dateTime)))
@@ -0,0 +1,19 @@
1
+ import oracledb
2
+
3
+ from modulitiz_micro.database.ModuloSqlServer import ModuloSqlServer
4
+
5
+
6
+ class ModuloSqlOracle(ModuloSqlServer):
7
+ DEFAULT_PORT=1521
8
+
9
+ def __init__(self,port:int|None,*args,**kwargs):
10
+ super().__init__(*args,**kwargs)
11
+ if port is None:
12
+ port=self.DEFAULT_PORT
13
+ self.port=port
14
+
15
+ def connessione(self):
16
+ dsn="{}/{}@{}:{}/xe".format(self.username,self.password,self.host,self.port)
17
+ self.connDb=oracledb.connect(dsn)
18
+ self.connDb=dsn
19
+
@@ -0,0 +1,43 @@
1
+ import pypyodbc
2
+
3
+ from modulitiz_nano.database.AbstractSql import AbstractSql
4
+
5
+
6
+ class ModuloSqlServer(AbstractSql):
7
+ ERROR_CODE__UNIQUE_INDEX=23000
8
+
9
+ def __init__(self,host:str,nome_db:str,username:str,password:str):
10
+ super().__init__()
11
+ self.host=host
12
+ self.nome_db=nome_db
13
+ self.username=username
14
+ self.password=password
15
+
16
+ def connessione(self):
17
+ connDb=pypyodbc.connect("Driver={SQL Server};Server="+self.host+";Database="+self.nome_db+";uid="+self.username+";pwd="+self.password+";")
18
+ self.connDb=connDb
19
+
20
+ def select(self,sql:str,params:list):
21
+ with self.initCursor() as cursoreDb:
22
+ cursoreDb.execute(sql,params)
23
+ results=list(cursoreDb)
24
+ return results
25
+
26
+ def select_count(self,cursoreDb,sql:str,params:list)->int:
27
+ with cursoreDb:
28
+ cursoreDb.execute(sql,params)
29
+ output=self.count(cursoreDb)
30
+ return output
31
+
32
+ def modifica(self,cursoreDb,sql:str,params:list,ignore_unique_index:bool):
33
+ """
34
+ Use it for data modifications like: insert, update, delete
35
+ """
36
+ try:
37
+ cursoreDb.execute(sql,params)
38
+ except pypyodbc.IntegrityError as ie:
39
+ if ignore_unique_index:
40
+ error_code=int(ie.value[0])
41
+ if error_code!=self.ERROR_CODE__UNIQUE_INDEX:
42
+ raise ie
43
+
@@ -0,0 +1,7 @@
1
+ from modulitiz_nano.exceptions.ExceptionNoData import ExceptionNoData
2
+
3
+
4
+ class ExceptionDbNoData(ExceptionNoData):
5
+
6
+ def __init__(self,*args):
7
+ super().__init__(*args)
@@ -0,0 +1,112 @@
1
+ from abc import abstractmethod
2
+
3
+ from modulitiz_micro.database.mysql.ModuloMysql import ModuloMysql
4
+ from modulitiz_nano.ModuloStringhe import ModuloStringhe
5
+
6
+
7
+ class AbstractBasicMysql(ModuloMysql):
8
+
9
+ def __init__(self,*args,**kwargs):
10
+ super().__init__(*args,**kwargs)
11
+
12
+ def initDdlBasicTables(self):
13
+ if not self.isDbNew:
14
+ return
15
+ sqlStr=ModuloStringhe.normalizzaEol(self.schemaBasicTables())
16
+ for results in self.executeScript(sqlStr):
17
+ yield results
18
+ sqlInsertBasicTables=self.insertBasicTables()
19
+ if not ModuloStringhe.isEmpty(sqlInsertBasicTables):
20
+ sqlInsertBasicTables=ModuloStringhe.normalizzaEol(sqlInsertBasicTables)
21
+ for results in self.executeScript(sqlInsertBasicTables):
22
+ yield results
23
+ self.commit()
24
+
25
+ def schemaBasicTables(self):
26
+ return """
27
+
28
+ CREATE TABLE tb_params(
29
+ id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
30
+ type1 CHAR(30) NOT NULL,
31
+ key1 CHAR(30) NOT NULL,
32
+ desc1 CHAR(100) NOT NULL,
33
+ enabled BOOLEAN NOT NULL,
34
+ lang_code CHAR(2) NULL,
35
+ data_insert DATETIME NOT NULL
36
+ )"""+self.TABLE_OPTIONS+""";
37
+ CREATE UNIQUE INDEX PARAMS__UK1 ON tb_params(type1,key1,lang_code);
38
+
39
+ """
40
+
41
+ @abstractmethod
42
+ def insertBasicTables(self):
43
+ """
44
+ Inserire le istruzioni sql che vanno eseguite alla fine di tutto
45
+ """
46
+
47
+
48
+
49
+ #############################################################################################################################
50
+ #############################################################################################################################
51
+ #############################################################################################################################
52
+ def selectParamDescByEntries(self,paramType:str,paramKey:str|None)->str|None:
53
+ with self.lock:
54
+ cursoreDb=self.selectParamByEntries(paramType, paramKey, None, True)
55
+ results=self.fetchAll(cursoreDb)
56
+ if len(results)==0:
57
+ return None
58
+ result=results[0]
59
+ return result['desc1']
60
+
61
+ def selectParamByEntries(self,paramType:str,paramKey:str|None,langCode:str|None,enabled:bool|None):
62
+ addParamKey=ModuloStringhe.isEmpty(paramKey) is False
63
+ addLangCode=ModuloStringhe.isEmpty(langCode) is False
64
+ addEnabled=enabled is not None
65
+
66
+ sql="""
67
+ SELECT *
68
+ FROM tb_params
69
+ WHERE type1=%(paramType)s
70
+ """+("AND key1=%(paramKey)s" if addParamKey is True else "")+"""
71
+ """+("AND langCode=%(langCode)s" if addLangCode is True else "")+"""
72
+ """+("AND enabled=%(enabled)s" if addEnabled is True else "")+"""
73
+ ;
74
+ """
75
+ params= {'paramType': paramType}
76
+ if addParamKey is True:
77
+ params['paramKey']=paramKey
78
+ if addLangCode is True:
79
+ params['langCode']=langCode
80
+ if addEnabled is True:
81
+ params['enabled']=enabled
82
+
83
+ cursoreDb=self.initCursor()
84
+ cursoreDb.execute(sql,params)
85
+ return cursoreDb
86
+
87
+
88
+ def updateParamDesc(self,paramType:str,paramKey:str|None,newDesc:str|None):
89
+ addParamKey=ModuloStringhe.isEmpty(paramKey) is False
90
+ addNewDesc=ModuloStringhe.isEmpty(newDesc) is False
91
+
92
+ sqlSet=[]
93
+ if addNewDesc is True:
94
+ sqlSet.append("desc1=%(newDesc)s")
95
+ sqlSet=", ".join(sqlSet)
96
+
97
+ sql="""
98
+ UPDATE tb_params
99
+ SET """+sqlSet+"""
100
+ WHERE type1=%(paramType)s
101
+ """+("AND key1=%(paramKey)s" if addParamKey is True else "")+"""
102
+ ;
103
+ """
104
+ params={}
105
+ if addNewDesc is True:
106
+ params['newDesc']=newDesc
107
+ params['paramType']=paramType
108
+ if addParamKey is True:
109
+ params['paramKey']=paramKey
110
+ cursoreDb=self.initCursor()
111
+ cursoreDb.execute(sql,params)
112
+ return cursoreDb
@@ -0,0 +1,157 @@
1
+ from abc import abstractmethod
2
+
3
+ import mysql.connector
4
+
5
+ from modulitiz_micro.database.exceptions.ExceptionDbNoData import ExceptionDbNoData
6
+ from modulitiz_micro.database.mysql.MysqlCommonConverter import MysqlCommonConverter
7
+ from modulitiz_nano.ModuloListe import ModuloListe
8
+ from modulitiz_nano.ModuloStringhe import ModuloStringhe
9
+ from modulitiz_nano.database.AbstractSql import AbstractSql
10
+ from modulitiz_nano.exceptions.ExceptionRuntime import ExceptionRuntime
11
+ from modulitiz_nano.files.ModuloFiles import ModuloFiles
12
+ from modulitiz_nano.sistema.ModuloSystem import ModuloSystem
13
+
14
+
15
+ class ModuloMysql(AbstractSql):
16
+ """
17
+ select
18
+ count
19
+ insert
20
+ update
21
+ delete
22
+ """
23
+
24
+ DATE_TIME_NOW="NOW()"
25
+
26
+ DEFAULT_PORT=3306
27
+
28
+
29
+ def __init__(self,host: str,port: int|None,user: str,password: str,nomeDb: str,isDebug: bool):
30
+ super().__init__()
31
+ self.nomeDb=nomeDb
32
+ if port is None:
33
+ port=self.DEFAULT_PORT
34
+ # open connection
35
+ self.connDb=mysql.connector.connect(user=user,password=password,host=host,port=port,
36
+ converter_class=MysqlCommonConverter)
37
+ self.TABLE_OPTIONS=self.getTableOptions(isDebug)
38
+ self.isDbNew=None
39
+
40
+ @abstractmethod
41
+ def schema(self):
42
+ """
43
+ Insert here sql instructions containing table definitions (DDL)
44
+ """
45
+
46
+ def initDdl(self):
47
+ #scelgo il db
48
+ try:
49
+ self.connDb.cmd_init_db(self.nomeDb)
50
+ self.isDbNew=False
51
+ except mysql.connector.ProgrammingError:
52
+ sqlCreaDb="CREATE DATABASE %s;"%(self.nomeDb,)
53
+ with self.initCursor() as cursoreDb:
54
+ cursoreDb.execute(sqlCreaDb)
55
+ self.connDb.cmd_init_db(self.nomeDb)
56
+ self.isDbNew=True
57
+ #se il db non esisteva creo le tabelle
58
+ if self.isDbNew:
59
+ sqlStr=ModuloStringhe.normalizzaEol(self.schema())
60
+ for results in self.executeScript(sqlStr):
61
+ yield results
62
+
63
+ @staticmethod
64
+ def getLastIdInserted(cursoreDb):
65
+ return cursoreDb.lastrowid
66
+
67
+ def selectNow(self):
68
+ """
69
+ Returns current db date and time.
70
+ """
71
+ sql="SELECT {};".format(self.DATE_TIME_NOW)
72
+ with self.initCursor() as cursoreDb:
73
+ cursoreDb.execute(sql,{})
74
+ output=self.fetchOne(cursoreDb)
75
+ return output
76
+
77
+ def executeScript(self,sqlStr:str):
78
+ sqlCmds=sqlStr.split(";")
79
+ sqlCmds=ModuloListe.eliminaElementiVuoti(sqlCmds)
80
+ numCmds=len(sqlCmds)
81
+ with self.initCursor() as cursoreDb:
82
+ for index,sqlCmd in enumerate(sqlCmds):
83
+ sqlCmd=sqlCmd.strip()
84
+ try:
85
+ if sqlCmd!="":
86
+ cursoreDb.execute(sqlCmd)
87
+ yield index,numCmds
88
+ except Exception as ex:
89
+ raise ExceptionRuntime(sqlCmd) from ex
90
+
91
+ def fetchAll(self,cursoreDb)->list:
92
+ with cursoreDb:
93
+ if cursoreDb.description is None:
94
+ raise ExceptionDbNoData()
95
+ descriptions=cursoreDb.description
96
+ rows=cursoreDb.fetchall()
97
+ self.commit() # mysql mette in cache i risultati, lo risolvo così, è un bug loro...
98
+ columns = [col[0] for col in descriptions]
99
+ rows = [dict(zip(columns, row)) for row in rows]
100
+ return rows
101
+
102
+ @classmethod
103
+ def backup(cls,percorsoCartella: str,user: str,password: str,dbName: str,
104
+ ignoreTables:list|tuple|None)->list:
105
+ output=[
106
+ cls.backupDdl(percorsoCartella,user,password,dbName,ignoreTables),
107
+ cls.backupData(percorsoCartella,user,password,dbName,ignoreTables)
108
+ ]
109
+ return output
110
+
111
+ @classmethod
112
+ def backupDdl(cls,percorsoCartella: str,user: str,password: str,dbName: str,
113
+ ignoreTables:list|tuple|None)->str:
114
+ return cls.__backup(percorsoCartella,user,password,dbName,ignoreTables,True,False)
115
+ @classmethod
116
+ def backupData(cls,percorsoCartella: str,user: str,password: str,dbName: str,
117
+ ignoreTables:list|tuple|None)->str:
118
+ return cls.__backup(percorsoCartella,user,password,dbName,ignoreTables,False,True)
119
+
120
+ @staticmethod
121
+ def __backup(percorsoCartella:str,user:str,password:str,dbName:str,
122
+ ignoreTables:list|tuple|None,onlyDdl:bool,onlyData:bool)->str:
123
+ if onlyDdl and onlyData:
124
+ raise ExceptionRuntime("valorizzare solo un'opzione alla volta")
125
+ cmdIgnoreTables=""
126
+ if ignoreTables is not None:
127
+ cmdIgnoreTables=" ".join(["--ignore-table=%s.%s"%(dbName,x) for x in ignoreTables])
128
+ nomefileSuffix=""
129
+ cmdOptions=""
130
+ if onlyDdl:
131
+ nomefileSuffix="_ddl"
132
+ cmdOptions="--no-data "+cmdIgnoreTables
133
+ elif onlyData:
134
+ nomefileSuffix="_data"
135
+ cmdOptions="--order-by-primary --no-create-info --quick "+cmdIgnoreTables
136
+ nomefileOutput=dbName+nomefileSuffix+".sql"
137
+ percorsoFileBackup=ModuloFiles.pathJoin(percorsoCartella,nomefileOutput)
138
+ cmd=r'mysqldump -u {} -p{} --databases {} --skip-add-drop-table --skip-comments {} -r "{}"'.format(user,password,dbName,cmdOptions,percorsoFileBackup)
139
+ output=ModuloSystem.systemCallReturnOutput(cmd,None).strip()
140
+ if not ModuloStringhe.isEmpty(output):
141
+ raise ExceptionRuntime(output)
142
+ return percorsoFileBackup
143
+
144
+ @staticmethod
145
+ def getTableOptions(isDebug: bool) -> str:
146
+ return "ENGINE=%s DEFAULT CHARSET=utf8"%("InnoDB" if not isDebug else "MEMORY",)
147
+
148
+ def paginazione(firstResult:int|None,numResults:int|None)->str:
149
+ sql=("LIMIT "+str(numResults) if numResults is not None else "")+\
150
+ (" OFFSET "+str(firstResult) if firstResult is not None else "")
151
+ return sql
152
+
153
+ def add_param_list(lista:list,prefix:str)->dict:
154
+ params={}
155
+ for index,elem in enumerate(lista):
156
+ params[prefix+str(index)]=elem
157
+ return params
@@ -0,0 +1,55 @@
1
+ from typing import Optional
2
+ from typing import override
3
+
4
+ from mysql.connector import FieldType
5
+ from mysql.connector.conversion import MySQLConverter
6
+ from mysql.connector.types import DescriptionType
7
+ from mysql.connector.types import MySQLConvertibleType
8
+ from mysql.connector.types import MySQLProducedType
9
+ from mysql.connector.types import PythonProducedType
10
+
11
+
12
+ class MysqlCommonConverter(MySQLConverter):
13
+ def __init__(self,charset: str|None = None,
14
+ use_unicode: bool = True,
15
+ str_fallback: bool = False):
16
+ super().__init__(charset,use_unicode,str_fallback)
17
+
18
+ @override
19
+ @classmethod
20
+ def _bit_to_python(cls,value: bytes, dsc: Optional[DescriptionType] = None) -> bool:
21
+ return super()._bit_to_python(value, dsc)==1
22
+
23
+ @override
24
+ def to_mysql(self,value) -> MySQLProducedType:
25
+ value=self.__to_mysql(value)
26
+ # default behavior
27
+ return super().to_mysql(value)
28
+
29
+ @staticmethod
30
+ def __to_mysql(value):
31
+ """
32
+ Gestione custom, ad esempio per IntEnum e StrEnum
33
+ """
34
+ if value.__class__ in MySQLConvertibleType.__args__:
35
+ return value
36
+ # inizio gestione custom
37
+ if isinstance(value,int):
38
+ typePrimitive=int
39
+ elif isinstance(value,str):
40
+ typePrimitive=str
41
+ else:
42
+ return value
43
+ value.__class__.__name__=typePrimitive.__name__
44
+ return value
45
+
46
+ @override
47
+ def to_python(
48
+ self,
49
+ vtype: DescriptionType,
50
+ value: Optional[bytes],
51
+ ) -> PythonProducedType:
52
+ if vtype[1] == FieldType.BIT:
53
+ return value==b'\x01'
54
+ # default behavior
55
+ return super().to_python(vtype, value)
@@ -0,0 +1,6 @@
1
+ import mysql.connector
2
+
3
+ class ExceptionMysqlOffline(mysql.connector.InterfaceError):
4
+
5
+ def __init__(self,*args,**kwargs):
6
+ super().__init__(*args,**kwargs)
@@ -0,0 +1,48 @@
1
+ from bs4 import BeautifulSoup
2
+ from bs4 import ResultSet
3
+ from bs4 import Tag
4
+
5
+ from modulitiz_nano.files.ModuloFiles import ModuloFiles
6
+
7
+
8
+ class DomModule(object):
9
+ def __init__(self, filePath: str|None, htmlString: str|None):
10
+ if filePath is not None:
11
+ self.filePath=filePath
12
+ htmlString=ModuloFiles.readFileText(filePath, True)
13
+ self.htmlString=htmlString
14
+ self.dom=self.__createObj()
15
+
16
+ @staticmethod
17
+ def innerHTML(tag:Tag)->str:
18
+ """
19
+ dato in input un tag html della classe BeautifulSoup, restituisce il codice html all'interno di questo tag
20
+ """
21
+ return "".join([str(x) for x in tag.contents])
22
+
23
+ def selector(self,cssSelector:str)->ResultSet[Tag]:
24
+ """
25
+ estrae tutti gli elementi che corrispondono al css selector
26
+ """
27
+ return self.dom.select(cssSelector)
28
+
29
+ @staticmethod
30
+ def getAttributeValue(tag:Tag, nomeAttr:str):
31
+ return tag.attrs[nomeAttr]
32
+
33
+ @staticmethod
34
+ def setAttributeValue(tag:Tag, nomeAttr:str, value):
35
+ tag.attrs[nomeAttr]=value
36
+ return tag
37
+
38
+ @staticmethod
39
+ def setInnerHtml(tag:Tag, value):
40
+ tag.string=value
41
+
42
+ def save(self):
43
+ htmlOut=str(self.dom).encode()
44
+ with open(self.filePath, "wb") as file:
45
+ file.write(htmlOut)
46
+
47
+ def __createObj(self)->BeautifulSoup:
48
+ return BeautifulSoup(self.htmlString, features="xml")
@@ -0,0 +1,7 @@
1
+ from modulitiz_nano.exceptions.ExceptionBase import ExceptionBase
2
+
3
+
4
+ class ExceptionCtrlC(ExceptionBase):
5
+
6
+ def __init__(self,*args):
7
+ super().__init__(*args)
@@ -0,0 +1,7 @@
1
+ from modulitiz_nano.exceptions.ExceptionBase import ExceptionBase
2
+
3
+
4
+ class ExceptionScheduler(ExceptionBase):
5
+
6
+ def __init__(self,*args):
7
+ super().__init__(*args)
@@ -0,0 +1,8 @@
1
+ from modulitiz_nano.exceptions.ExceptionBase import ExceptionBase
2
+
3
+
4
+ class ExceptionHttp(ExceptionBase):
5
+
6
+ def __init__(self,httpCode:int|None,*args):
7
+ super().__init__(*args)
8
+ self.httpCode=httpCode
@@ -0,0 +1,7 @@
1
+ from modulitiz_micro.exceptions.http.ExceptionHttp import ExceptionHttp
2
+
3
+
4
+ class ExceptionHttp404(ExceptionHttp):
5
+
6
+ def __init__(self):
7
+ super().__init__(404)
@@ -0,0 +1,7 @@
1
+ from modulitiz_micro.exceptions.http.ExceptionHttp import ExceptionHttp
2
+
3
+
4
+ class ExceptionHttpGeneric(ExceptionHttp):
5
+
6
+ def __init__(self):
7
+ super().__init__(None)
@@ -0,0 +1,7 @@
1
+ from modulitiz_micro.exceptions.http.ExceptionHttpGeneric import ExceptionHttpGeneric
2
+
3
+
4
+ class ExceptionHttpRetriesExceeded(ExceptionHttpGeneric):
5
+
6
+ def __init__(self):
7
+ super().__init__()
@@ -0,0 +1,26 @@
1
+ from functools import wraps
2
+
3
+ from cachetools import TTLCache
4
+ from cachetools import cached
5
+
6
+ from modulitiz_nano.ModuloNumeri import ModuloNumeri
7
+
8
+
9
+ def cacheRam(minsBeforeExpiry: int|float|None):
10
+ """
11
+ Usare questo decorator per mettere in cache delle informazioni.
12
+ Alla base usa una libreria di terze parti.
13
+ :param minsBeforeExpiry: se null mantiene i dati in memoria per 1 giorno
14
+ """
15
+
16
+ __secsBeforeExpiry=24*3600 if minsBeforeExpiry is None else ModuloNumeri.decimalNumbersTruncate(minsBeforeExpiry*60,2)
17
+ __cache=cached(TTLCache(20,__secsBeforeExpiry))
18
+
19
+ def decorator(funzione):
20
+ __funzione=__cache(funzione)
21
+
22
+ @wraps(funzione)
23
+ def wrapped(*args,**kwargs):
24
+ return __funzione(*args,**kwargs)
25
+ return wrapped
26
+ return decorator
@@ -0,0 +1,32 @@
1
+ import git
2
+
3
+ from modulitiz_micro.files.git.decorators.catchAndRaiseGitExceptions import catchAndRaiseGitExceptions
4
+
5
+
6
+ class ModuloGit(object):
7
+ def __init__(self, repoPath:str):
8
+ self.inner=git.Repo(repoPath)
9
+
10
+ @catchAndRaiseGitExceptions
11
+ def getWorkingCopyRevision(self)->str:
12
+ return self.inner.head.object.hexsha
13
+
14
+ @catchAndRaiseGitExceptions
15
+ def getRemoteRevision(self)->str:
16
+ return self.inner.remotes[0].fetch()[0].ref.object.hexsha
17
+
18
+ @catchAndRaiseGitExceptions
19
+ def addFile(self,filenamePath:str):
20
+ self.inner.index.add(filenamePath)
21
+
22
+ @catchAndRaiseGitExceptions
23
+ def removeFile(self,filenamePath:str):
24
+ self.inner.index.remove(filenamePath,working_tree=True)
25
+
26
+ @catchAndRaiseGitExceptions
27
+ def resetCurrentLocalBranch(self):
28
+ self.inner.head.reset(working_tree=True)
29
+
30
+ @catchAndRaiseGitExceptions
31
+ def update(self)->str:
32
+ return self.inner.remotes[0].pull()[0].ref.object.hexsha
@@ -0,0 +1,19 @@
1
+ from functools import wraps
2
+
3
+ from git import GitCommandError
4
+
5
+ from modulitiz_micro.files.git.exceptions.ExceptionGit import ExceptionGit
6
+
7
+
8
+ def catchAndRaiseGitExceptions(function):
9
+ """
10
+ Cattura tutte le eccezioni git di vario tipo e rilancia un'eccezione custom
11
+ """
12
+
13
+ @wraps(function)
14
+ def wrapped(*args,**kwargs):
15
+ try:
16
+ return function(*args,**kwargs)
17
+ except (GitCommandError,) as ex:
18
+ raise ExceptionGit() from ex
19
+ return wrapped
@@ -0,0 +1,7 @@
1
+ from modulitiz_nano.exceptions.ExceptionBase import ExceptionBase
2
+
3
+
4
+ class ExceptionGit(ExceptionBase):
5
+
6
+ def __init__(self,*args):
7
+ super().__init__(*args)