articlib 0.2.1__tar.gz
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 articlib might be problematic. Click here for more details.
- articlib-0.2.1/LICENSE +21 -0
- articlib-0.2.1/PKG-INFO +68 -0
- articlib-0.2.1/README.md +51 -0
- articlib-0.2.1/articlib/articFileUtils.py +54 -0
- articlib-0.2.1/articlib/articLogger.py +102 -0
- articlib-0.2.1/articlib/consoleUtils.py +36 -0
- articlib-0.2.1/articlib/dateTime.py +121 -0
- articlib-0.2.1/articlib/dice.py +32 -0
- articlib-0.2.1/articlib/sqliteEngine.py +66 -0
- articlib-0.2.1/articlib/systemUtils.py +34 -0
- articlib-0.2.1/articlib/testEngine.py +111 -0
- articlib-0.2.1/pyproject.toml +16 -0
articlib-0.2.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Iñaki Arrondo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
articlib-0.2.1/PKG-INFO
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: articlib
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Small set of tools and utilities in python. Destined to be use in my personal projects.
|
|
5
|
+
License: MIT
|
|
6
|
+
Author: Artic42
|
|
7
|
+
Author-email: engineer@artic42.com
|
|
8
|
+
Requires-Python: >=3.10,<4.0
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Requires-Dist: colorama (>=0.4.6,<0.5.0)
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# pythonLib
|
|
18
|
+
|
|
19
|
+
This is my personal general case python modules and apps to be used in other projects
|
|
20
|
+
|
|
21
|
+
## testEngine
|
|
22
|
+
|
|
23
|
+
Test engine is a simple module with the propose of running automated test, this allows to create test for the rest of the library easily. Test are separated in scenario, once a test in a scenario fail the rest of the scenario is skipped. It also outputs using colored test with errors in red and pass test in green. It has the following methods:
|
|
24
|
+
* testIfEqual
|
|
25
|
+
* testIfFalse
|
|
26
|
+
* testIfEqual
|
|
27
|
+
* testIfNotEqual
|
|
28
|
+
* ...
|
|
29
|
+
|
|
30
|
+
## dateTime
|
|
31
|
+
|
|
32
|
+
Library to manage dates for other proposes.
|
|
33
|
+
|
|
34
|
+
Public methods for setting dates
|
|
35
|
+
* __setToNow__
|
|
36
|
+
* __setTo__ (year, month, day, hour, minute, second)
|
|
37
|
+
* __setToString__ (string)
|
|
38
|
+
* __setMode__ (mode)
|
|
39
|
+
* _mode1_: YYYYMMDD
|
|
40
|
+
* _mode2_: DDMMYYYY
|
|
41
|
+
* _mode3_: MMDDYYYY
|
|
42
|
+
|
|
43
|
+
Public methods to get values from the object
|
|
44
|
+
* __getDate__
|
|
45
|
+
* __getTime__
|
|
46
|
+
* __getDateTime__
|
|
47
|
+
* __getYear__
|
|
48
|
+
* __getMonth__
|
|
49
|
+
* __getDay__
|
|
50
|
+
* __getHour__
|
|
51
|
+
* __getMinute__
|
|
52
|
+
* __getSecond__
|
|
53
|
+
* __getMode__
|
|
54
|
+
* __getDateTimePathFomat__ (It prints the date and time in a format usable in paths, for files)
|
|
55
|
+
|
|
56
|
+
## Log
|
|
57
|
+
|
|
58
|
+
A simple log system, it creates a log iwth 7 mask levels and a maximun size of file. If you log more lines than max it creates a new log file. Available masks
|
|
59
|
+
|
|
60
|
+
* INFO_MASK
|
|
61
|
+
* WARN_MASK
|
|
62
|
+
* ERROR_MASK
|
|
63
|
+
* COMMS_SEND_MASK
|
|
64
|
+
* COMMS_RECV_MASK
|
|
65
|
+
* HERMES_MASK000
|
|
66
|
+
* COMMS_MASK
|
|
67
|
+
* DEBUG_MASK
|
|
68
|
+
|
articlib-0.2.1/README.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# pythonLib
|
|
2
|
+
|
|
3
|
+
This is my personal general case python modules and apps to be used in other projects
|
|
4
|
+
|
|
5
|
+
## testEngine
|
|
6
|
+
|
|
7
|
+
Test engine is a simple module with the propose of running automated test, this allows to create test for the rest of the library easily. Test are separated in scenario, once a test in a scenario fail the rest of the scenario is skipped. It also outputs using colored test with errors in red and pass test in green. It has the following methods:
|
|
8
|
+
* testIfEqual
|
|
9
|
+
* testIfFalse
|
|
10
|
+
* testIfEqual
|
|
11
|
+
* testIfNotEqual
|
|
12
|
+
* ...
|
|
13
|
+
|
|
14
|
+
## dateTime
|
|
15
|
+
|
|
16
|
+
Library to manage dates for other proposes.
|
|
17
|
+
|
|
18
|
+
Public methods for setting dates
|
|
19
|
+
* __setToNow__
|
|
20
|
+
* __setTo__ (year, month, day, hour, minute, second)
|
|
21
|
+
* __setToString__ (string)
|
|
22
|
+
* __setMode__ (mode)
|
|
23
|
+
* _mode1_: YYYYMMDD
|
|
24
|
+
* _mode2_: DDMMYYYY
|
|
25
|
+
* _mode3_: MMDDYYYY
|
|
26
|
+
|
|
27
|
+
Public methods to get values from the object
|
|
28
|
+
* __getDate__
|
|
29
|
+
* __getTime__
|
|
30
|
+
* __getDateTime__
|
|
31
|
+
* __getYear__
|
|
32
|
+
* __getMonth__
|
|
33
|
+
* __getDay__
|
|
34
|
+
* __getHour__
|
|
35
|
+
* __getMinute__
|
|
36
|
+
* __getSecond__
|
|
37
|
+
* __getMode__
|
|
38
|
+
* __getDateTimePathFomat__ (It prints the date and time in a format usable in paths, for files)
|
|
39
|
+
|
|
40
|
+
## Log
|
|
41
|
+
|
|
42
|
+
A simple log system, it creates a log iwth 7 mask levels and a maximun size of file. If you log more lines than max it creates a new log file. Available masks
|
|
43
|
+
|
|
44
|
+
* INFO_MASK
|
|
45
|
+
* WARN_MASK
|
|
46
|
+
* ERROR_MASK
|
|
47
|
+
* COMMS_SEND_MASK
|
|
48
|
+
* COMMS_RECV_MASK
|
|
49
|
+
* HERMES_MASK000
|
|
50
|
+
* COMMS_MASK
|
|
51
|
+
* DEBUG_MASK
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
def deleteFile(path):
|
|
4
|
+
os.remove(path)
|
|
5
|
+
|
|
6
|
+
def createFile(path):
|
|
7
|
+
file = open (path, "r")
|
|
8
|
+
file.close()
|
|
9
|
+
|
|
10
|
+
def fileExists(path):
|
|
11
|
+
return os.path.isfile(path)
|
|
12
|
+
|
|
13
|
+
def getFilesInDirectory(path):
|
|
14
|
+
return os.listdir(path)
|
|
15
|
+
|
|
16
|
+
def deleteDirectory(path):
|
|
17
|
+
os.rmdir(path)
|
|
18
|
+
|
|
19
|
+
def createDirectory(path):
|
|
20
|
+
os.makedirs(path, exist_ok=True)
|
|
21
|
+
|
|
22
|
+
class FileIO:
|
|
23
|
+
def __init__(self, path, readIt = False):
|
|
24
|
+
self.path = path
|
|
25
|
+
if readIt:
|
|
26
|
+
self.readFile()
|
|
27
|
+
else:
|
|
28
|
+
lines = []
|
|
29
|
+
|
|
30
|
+
def readFile(self):
|
|
31
|
+
filePointer = open (self.path, "r")
|
|
32
|
+
self.lines = filePointer.readlines()
|
|
33
|
+
filePointer.close()
|
|
34
|
+
|
|
35
|
+
def writeFile(self):
|
|
36
|
+
filePointer = open (self.path, "w")
|
|
37
|
+
for line in self.lines:
|
|
38
|
+
filePointer.write(line + "\n")
|
|
39
|
+
filePointer.close()
|
|
40
|
+
|
|
41
|
+
def appendToFile(self):
|
|
42
|
+
filePointer = open (self.path, "a")
|
|
43
|
+
for line in self.lines:
|
|
44
|
+
filePointer.write(line + "\n")
|
|
45
|
+
filePointer.close()
|
|
46
|
+
|
|
47
|
+
def addLine(self, line):
|
|
48
|
+
self.lines.append(line)
|
|
49
|
+
|
|
50
|
+
def modifyLine(self, lineNumber, line):
|
|
51
|
+
self.lines[lineNumber] = line
|
|
52
|
+
|
|
53
|
+
def lineCount(self):
|
|
54
|
+
return len(self.lines)
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import dateTime
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
if __name__ == "__main__":
|
|
5
|
+
pass
|
|
6
|
+
|
|
7
|
+
INFO_MASK = 0b00000001
|
|
8
|
+
WARN_MASK = 0b00000010
|
|
9
|
+
ERROR_MASK = 0b00000100
|
|
10
|
+
COMMS_SEND_MASK = 0b00001000
|
|
11
|
+
COMMS_RECV_MASK = 0b00010000
|
|
12
|
+
HERMES_MASK = 0b00100000
|
|
13
|
+
COMMS_MASK= 0b00011000
|
|
14
|
+
DEBUG_MASK = 0b01000000
|
|
15
|
+
DEFAULT_MASK = INFO_MASK | COMMS_MASK | ERROR_MASK | HERMES_MASK
|
|
16
|
+
|
|
17
|
+
class Logger:
|
|
18
|
+
def __init__(self):
|
|
19
|
+
self.init = False
|
|
20
|
+
self.logName = ""
|
|
21
|
+
self.maxLines = 0
|
|
22
|
+
self.lines = 0
|
|
23
|
+
self.logPath = ""
|
|
24
|
+
self.mask = 0b0
|
|
25
|
+
|
|
26
|
+
def initialize(self, logName, maxLines = 1000, logPath = "logs", mask = DEFAULT_MASK):
|
|
27
|
+
self.init = True
|
|
28
|
+
self.logName = logName
|
|
29
|
+
self.maxLines = maxLines
|
|
30
|
+
self.lines = 0
|
|
31
|
+
self.logPath = logPath
|
|
32
|
+
self.mask = mask
|
|
33
|
+
self.date = dateTime.createDate(dateTime.YYYYMMDD)
|
|
34
|
+
self.createLogFile()
|
|
35
|
+
|
|
36
|
+
def createLogFile(self):
|
|
37
|
+
self.date.setToNow()
|
|
38
|
+
dateSring = self.date.getDateTimePathFomat()
|
|
39
|
+
os.makedirs(self.logPath, exist_ok=True)
|
|
40
|
+
self.logFilePath = self.logPath + "/" + self.logName + "_" + dateSring + ".log"
|
|
41
|
+
if os.path.isfile(self.logFilePath):
|
|
42
|
+
self.logFile = open(self.logFilePath, "a")
|
|
43
|
+
else:
|
|
44
|
+
self.logFile = open(self.logFilePath, "w")
|
|
45
|
+
self.logFile.write(f"Log file created at {self.date.getDateTime()} with name {self.logName}\n")
|
|
46
|
+
self.lines = 0
|
|
47
|
+
|
|
48
|
+
def addEntry(self, message, mask = INFO_MASK):
|
|
49
|
+
maskName = self.getMaskName(mask)
|
|
50
|
+
if mask & self.mask:
|
|
51
|
+
if self.init:
|
|
52
|
+
self.writeLog(message, maskName)
|
|
53
|
+
|
|
54
|
+
def getMaskName(self, mask):
|
|
55
|
+
switcher = {
|
|
56
|
+
INFO_MASK: "INFO",
|
|
57
|
+
WARN_MASK: "WARN",
|
|
58
|
+
ERROR_MASK: "ERROR",
|
|
59
|
+
COMMS_SEND_MASK: "COMMS_SEND",
|
|
60
|
+
COMMS_RECV_MASK: "COMMS_RECV",
|
|
61
|
+
HERMES_MASK: "HERMES",
|
|
62
|
+
DEBUG_MASK: "DEBUG",
|
|
63
|
+
DEFAULT_MASK: "DEFAULT"
|
|
64
|
+
}
|
|
65
|
+
return switcher.get(mask, "UNKNOWN")
|
|
66
|
+
|
|
67
|
+
def writeLog(self, message, maskName):
|
|
68
|
+
self.date.setToNow()
|
|
69
|
+
dateSring = self.date.getDateTime()
|
|
70
|
+
self.lines += 1
|
|
71
|
+
self.logFile.write(f"{dateSring} - {maskName} - {message}\n")
|
|
72
|
+
if self.lines >= self.maxLines:
|
|
73
|
+
self.logFile.close()
|
|
74
|
+
self.createLogFile()
|
|
75
|
+
|
|
76
|
+
def setMask(self, mask):
|
|
77
|
+
self.mask = mask
|
|
78
|
+
|
|
79
|
+
def getMask(self):
|
|
80
|
+
return self.mask
|
|
81
|
+
|
|
82
|
+
def setValueInMask(self, mask):
|
|
83
|
+
self.mask = self.mask | mask
|
|
84
|
+
|
|
85
|
+
def unsetValueInMask(self, mask):
|
|
86
|
+
self.mask = self.mask & ~mask
|
|
87
|
+
|
|
88
|
+
def flush(self):
|
|
89
|
+
self.logFile.flush()
|
|
90
|
+
|
|
91
|
+
def restartFile(self):
|
|
92
|
+
self.logFile.close()
|
|
93
|
+
self.lines = 0
|
|
94
|
+
self.createLogFile()
|
|
95
|
+
|
|
96
|
+
def getLogFilePath(self):
|
|
97
|
+
return self.logFilePath
|
|
98
|
+
|
|
99
|
+
def close(self):
|
|
100
|
+
self.logFile.close()
|
|
101
|
+
|
|
102
|
+
log = Logger()
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import colorama
|
|
2
|
+
from colorama import Fore, Back, Style
|
|
3
|
+
|
|
4
|
+
def printRed(text):
|
|
5
|
+
print(Fore.RED + text + Style.RESET_ALL)
|
|
6
|
+
|
|
7
|
+
def printGreen(text):
|
|
8
|
+
print(Fore.GREEN + text + Style.RESET_ALL)
|
|
9
|
+
|
|
10
|
+
def printYellow(text):
|
|
11
|
+
print(Fore.YELLOW + text + Style.RESET_ALL)
|
|
12
|
+
|
|
13
|
+
def printBlue(text):
|
|
14
|
+
print(Fore.BLUE + text + Style.RESET_ALL)
|
|
15
|
+
|
|
16
|
+
def printMagenta(text):
|
|
17
|
+
print(Fore.MAGENTA + text + Style.RESET_ALL)
|
|
18
|
+
|
|
19
|
+
def printBold(text):
|
|
20
|
+
print(Style.BRIGHT + text + Style.RESET_ALL)
|
|
21
|
+
|
|
22
|
+
def printRedBold(text):
|
|
23
|
+
print(Style.BRIGHT + Fore.RED + text + Style.RESET_ALL)
|
|
24
|
+
|
|
25
|
+
def printGreenBold(text):
|
|
26
|
+
print(Style.BRIGHT + Fore.GREEN + text + Style.RESET_ALL)
|
|
27
|
+
|
|
28
|
+
def printYellowBold(text):
|
|
29
|
+
print(Style.BRIGHT + Fore.YELLOW + text + Style.RESET_ALL)
|
|
30
|
+
|
|
31
|
+
def printBlueBold(text):
|
|
32
|
+
print(Style.BRIGHT + Fore.BLUE + text + Style.RESET_ALL)
|
|
33
|
+
|
|
34
|
+
def printMagentaBold(text):
|
|
35
|
+
print(Style.BRIGHT + Fore.MAGENTA + text + Style.RESET_ALL)
|
|
36
|
+
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
|
|
3
|
+
YYYYMMDD = 1
|
|
4
|
+
DDMMYYYY = 2
|
|
5
|
+
MMDDYYYY = 3
|
|
6
|
+
|
|
7
|
+
class createDate:
|
|
8
|
+
def __init__(self, mode):
|
|
9
|
+
self.mode = mode
|
|
10
|
+
|
|
11
|
+
def setToNow(self):
|
|
12
|
+
date = datetime.now()
|
|
13
|
+
self.year = int(date.year)
|
|
14
|
+
self.month = int(date.month)
|
|
15
|
+
self.day = int(date.day)
|
|
16
|
+
self.hour = int(date.hour)
|
|
17
|
+
self.minute = int(date.minute)
|
|
18
|
+
self.second = int(date.second)
|
|
19
|
+
self.calculateStringDate()
|
|
20
|
+
self.calculateStringTime()
|
|
21
|
+
|
|
22
|
+
def setTo(self, year, month, day, hour, minute, second):
|
|
23
|
+
self.year = year
|
|
24
|
+
self.month = month
|
|
25
|
+
self.day = day
|
|
26
|
+
self.hour = hour
|
|
27
|
+
self.minute = minute
|
|
28
|
+
self.second = second
|
|
29
|
+
self.calculateStringDate()
|
|
30
|
+
self.calculateStringTime()
|
|
31
|
+
|
|
32
|
+
def setToString(self, string):
|
|
33
|
+
string = string.split(" ")
|
|
34
|
+
date = string[0]
|
|
35
|
+
time = string[1]
|
|
36
|
+
self.dateString = date
|
|
37
|
+
self.timeString = time
|
|
38
|
+
self.calculateDate()
|
|
39
|
+
self.calculateTime()
|
|
40
|
+
|
|
41
|
+
def calculateDate(self):
|
|
42
|
+
if self.mode == YYYYMMDD:
|
|
43
|
+
self.year = int(self.dateString[0:4])
|
|
44
|
+
self.month = int(self.dateString[5:7])
|
|
45
|
+
self.day = int(self.dateString[8:10])
|
|
46
|
+
elif self.mode == DDMMYYYY:
|
|
47
|
+
self.day = int(self.dateString[0:2])
|
|
48
|
+
self.month = int(self.dateString[3:5])
|
|
49
|
+
self.year = int(self.dateString[6:10])
|
|
50
|
+
elif self.mode == MMDDYYYY:
|
|
51
|
+
self.month = int(self.dateString[0:2])
|
|
52
|
+
self.day = int(self.dateString[3:5])
|
|
53
|
+
self.year = int(self.dateString[6:10])
|
|
54
|
+
else:
|
|
55
|
+
raise ValueError("Invalid mode")
|
|
56
|
+
|
|
57
|
+
def calculateTime(self):
|
|
58
|
+
self.hour = int(self.timeString[0:2])
|
|
59
|
+
self.minute = int(self.timeString[3:5])
|
|
60
|
+
self.second = int(self.timeString[6:8])
|
|
61
|
+
|
|
62
|
+
def calculateStringDate(self):
|
|
63
|
+
if self.mode == YYYYMMDD:
|
|
64
|
+
self.dateString = str(self.year) + "/" + str(self.month).zfill(2) + "/" + str(self.day).zfill(2)
|
|
65
|
+
elif self.mode == DDMMYYYY:
|
|
66
|
+
self.dateString = str(self.day).zfill(2) + "/" + str(self.month).zfill(2) + "/" + str(self.year)
|
|
67
|
+
elif self.mode == MMDDYYYY:
|
|
68
|
+
self.dateString = str(self.month).zfill(2) + "/" + str(self.day).zfill(2) + "/" + str(self.year)
|
|
69
|
+
else:
|
|
70
|
+
raise ValueError("Invalid mode")
|
|
71
|
+
|
|
72
|
+
def calculateStringTime(self):
|
|
73
|
+
self.timeString = str(self.hour).zfill(2) + ":" + str(self.minute).zfill(2) + ":" + str(self.second).zfill(2)
|
|
74
|
+
|
|
75
|
+
def setMode(self, mode):
|
|
76
|
+
self.mode = mode
|
|
77
|
+
self.calculateStringDate()
|
|
78
|
+
|
|
79
|
+
## Output values
|
|
80
|
+
def getDateTimePathFomat(self):
|
|
81
|
+
if self.mode == YYYYMMDD:
|
|
82
|
+
dateString = str(self.year) + str(self.month).zfill(2) + str(self.day).zfill(2)
|
|
83
|
+
elif self.mode == DDMMYYYY:
|
|
84
|
+
dateString = str(self.day).zfill(2) + str(self.month).zfill(2) + str(self.year)
|
|
85
|
+
elif self.mode == MMDDYYYY:
|
|
86
|
+
dateString = str(self.month).zfill(2) + str(self.day).zfill(2) + str(self.year)
|
|
87
|
+
else:
|
|
88
|
+
raise ValueError("Invalid mode")
|
|
89
|
+
timeString = str(self.hour).zfill(2) + str(self.minute).zfill(2) + str(self.second).zfill(2)
|
|
90
|
+
return f"{dateString}_{timeString}"
|
|
91
|
+
|
|
92
|
+
def getDate(self):
|
|
93
|
+
return self.dateString
|
|
94
|
+
|
|
95
|
+
def getTime(self):
|
|
96
|
+
return self.timeString
|
|
97
|
+
|
|
98
|
+
def getDateTime(self):
|
|
99
|
+
return self.dateString + " " + self.timeString
|
|
100
|
+
|
|
101
|
+
def getYear(self):
|
|
102
|
+
return self.year
|
|
103
|
+
|
|
104
|
+
def getMonth(self):
|
|
105
|
+
return self.month
|
|
106
|
+
|
|
107
|
+
def getDay(self):
|
|
108
|
+
return self.day
|
|
109
|
+
|
|
110
|
+
def getHour(self):
|
|
111
|
+
return self.hour
|
|
112
|
+
|
|
113
|
+
def getMinute(self):
|
|
114
|
+
return self.minute
|
|
115
|
+
|
|
116
|
+
def getSecond(self):
|
|
117
|
+
return self.second
|
|
118
|
+
|
|
119
|
+
def getMode(self):
|
|
120
|
+
return self.mode
|
|
121
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import random
|
|
2
|
+
|
|
3
|
+
class dice:
|
|
4
|
+
def __init__(self, size=6):
|
|
5
|
+
self.size = size
|
|
6
|
+
|
|
7
|
+
def setSize(self, size):
|
|
8
|
+
self.size = size
|
|
9
|
+
|
|
10
|
+
def roll(self):
|
|
11
|
+
return random.randint(1, self.size)
|
|
12
|
+
|
|
13
|
+
class customDice(dice):
|
|
14
|
+
def __init__(self, faces):
|
|
15
|
+
self.faces = faces
|
|
16
|
+
self.size = len(faces)
|
|
17
|
+
|
|
18
|
+
def roll(self):
|
|
19
|
+
return random.choice(self.faces)
|
|
20
|
+
|
|
21
|
+
class dicePool:
|
|
22
|
+
def __init__(self, diceList):
|
|
23
|
+
self.diceList = diceList
|
|
24
|
+
|
|
25
|
+
def roll(self):
|
|
26
|
+
return [d.roll() for d in self.diceList]
|
|
27
|
+
|
|
28
|
+
def rollSum(self):
|
|
29
|
+
return sum(self.roll())
|
|
30
|
+
|
|
31
|
+
def rollSuccesses(self, target):
|
|
32
|
+
return sum([1 for roll in self.roll() if roll >= target])
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import sqlite3
|
|
2
|
+
import articLogger as Logger
|
|
3
|
+
from articLogger import log
|
|
4
|
+
|
|
5
|
+
class sqliteEngine:
|
|
6
|
+
def __init__(self, dbPath):
|
|
7
|
+
self.con = sqlite3.connect (dbPath)
|
|
8
|
+
self.cursor = self.con.cursor()
|
|
9
|
+
|
|
10
|
+
def executeCommand (self, command):
|
|
11
|
+
log.addEntry(f"Executing command: {command}", Logger.DEBUG_MASK)
|
|
12
|
+
self.cursor.execute (command)
|
|
13
|
+
|
|
14
|
+
def createTable (self, name, columns):
|
|
15
|
+
self.executeCommand (f"CREATE TABLE {name} ({columns});")
|
|
16
|
+
|
|
17
|
+
def addColumn (self, table, column):
|
|
18
|
+
self.executeCommand (f"ALTER TABLE {table} ADD COLUMN {column};")
|
|
19
|
+
|
|
20
|
+
def deleteColumn (self, table, column):
|
|
21
|
+
self.executeCommand (f"ALTER TABLE {table} DROP COLUMN {column}")
|
|
22
|
+
|
|
23
|
+
def addEntry (self, table, columns, values):
|
|
24
|
+
self.executeCommand (f"INSERT INTO {table} ({columns}) VALUES ({values});")
|
|
25
|
+
|
|
26
|
+
def updateEntry (self, table, columns, values, condition):
|
|
27
|
+
self.executeCommand (f"UPDATE {table} SET {columns} = {values} WHERE {condition};")
|
|
28
|
+
|
|
29
|
+
def deleteEntry (self, table, condition):
|
|
30
|
+
self.executeCommand (f"DELETE FROM {table} WHERE {condition};")
|
|
31
|
+
|
|
32
|
+
def readEntry (self, table, columns):
|
|
33
|
+
self.executeCommand (f"SELECT {columns} FROM {table};")
|
|
34
|
+
result = self.cursor.fetchall()
|
|
35
|
+
log.addEntry(f"Read entry: {result}", Logger.DEBUG_MASK)
|
|
36
|
+
return result
|
|
37
|
+
|
|
38
|
+
def readNumberOfEntries (self, table):
|
|
39
|
+
self.executeCommand (f"SELECT COUNT(*) FROM {table};")
|
|
40
|
+
result = self.cursor.fetchall()
|
|
41
|
+
log.addEntry(f"Read number of entries: {result}", Logger.DEBUG_MASK)
|
|
42
|
+
return result[0][0]
|
|
43
|
+
|
|
44
|
+
def readEntryFiltered (self, table, columns, filter):
|
|
45
|
+
self.executeCommand(f"SELECT {columns} FROM {table} WHERE {filter};")
|
|
46
|
+
result = self.cursor.fetchall()
|
|
47
|
+
log.addEntry(f"Read entry: {result}", Logger.DEBUG_MASK)
|
|
48
|
+
return result
|
|
49
|
+
|
|
50
|
+
def entryExistsOnTable (self, table, condition):
|
|
51
|
+
self.executeCommand (f"SELECT * FROM {table} WHERE {condition};")
|
|
52
|
+
entry = self.cursor.fetchall()
|
|
53
|
+
if len(entry) != 0:
|
|
54
|
+
return True
|
|
55
|
+
else:
|
|
56
|
+
return False
|
|
57
|
+
|
|
58
|
+
def deleteEntryFromTable (self, table, condition):
|
|
59
|
+
self.executeCommand (f"DELETE FROM {table} WHERE {condition};")
|
|
60
|
+
|
|
61
|
+
def commit(self):
|
|
62
|
+
self.con.commit()
|
|
63
|
+
|
|
64
|
+
def commitClose(self):
|
|
65
|
+
self.commit()
|
|
66
|
+
self.con.close()
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import datetime
|
|
3
|
+
|
|
4
|
+
def executeCommand(command):
|
|
5
|
+
result = subprocess.run(command)
|
|
6
|
+
return result.returncode
|
|
7
|
+
|
|
8
|
+
class command:
|
|
9
|
+
def __init__(self, command, run=True, capture=True, timeout=-1):
|
|
10
|
+
self.command = command
|
|
11
|
+
self.capture = capture
|
|
12
|
+
self.timeout = timeout
|
|
13
|
+
if run:
|
|
14
|
+
self.run
|
|
15
|
+
|
|
16
|
+
def run(self):
|
|
17
|
+
if self.timeout > 0:
|
|
18
|
+
self.process = subprocess.run(command, capture_output=self.capture, timeout=self.timeout)
|
|
19
|
+
else:
|
|
20
|
+
self.runWithoutTimeout
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def runWithoutTimeout(self):
|
|
24
|
+
self.process = subprocess.run(command, capture_output=self.capture)
|
|
25
|
+
|
|
26
|
+
def stdout(self):
|
|
27
|
+
return self.process.stdout
|
|
28
|
+
|
|
29
|
+
def stderr(self):
|
|
30
|
+
return self.process.stderr
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import articLogger as logger
|
|
2
|
+
from consoleUtils import printRed, printGreen, printYellow, printMagenta, printGreenBold, printRedBold
|
|
3
|
+
|
|
4
|
+
class testEngine:
|
|
5
|
+
def __init__(self):
|
|
6
|
+
self.passed = True
|
|
7
|
+
self.failed = False
|
|
8
|
+
self.escenarioPassed = True
|
|
9
|
+
self.escenarioFailed = False
|
|
10
|
+
self.testCount = 0
|
|
11
|
+
self.scenarioCount = 0
|
|
12
|
+
self.passCount = 0
|
|
13
|
+
self.failCount = 0
|
|
14
|
+
self.skipCount = 0
|
|
15
|
+
|
|
16
|
+
def testIfTrue(self, test, message):
|
|
17
|
+
if self.escenarioPassed:
|
|
18
|
+
self.testCount += 1
|
|
19
|
+
if test:
|
|
20
|
+
self.passCount += 1
|
|
21
|
+
printGreen(f"\tTest {self.testCount} passed: {message}")
|
|
22
|
+
return 1
|
|
23
|
+
else:
|
|
24
|
+
self.failCount += 1
|
|
25
|
+
printRed(f"\tTest {self.testCount} failed: {message}")
|
|
26
|
+
self.scenarioPassed = False
|
|
27
|
+
self.scenarioFailed= True
|
|
28
|
+
return 2
|
|
29
|
+
else:
|
|
30
|
+
self.skipCount += 1
|
|
31
|
+
printYellow(f"\tTest {self.testCount} skipped: {message}")
|
|
32
|
+
return 3
|
|
33
|
+
|
|
34
|
+
def testIfFalse(self, test, message):
|
|
35
|
+
self.testIfTrue(not test, message)
|
|
36
|
+
|
|
37
|
+
def testIfEqual(self, expected, testValue, message):
|
|
38
|
+
response = self.testIfTrue(expected == testValue, message)
|
|
39
|
+
if response == 2:
|
|
40
|
+
printMagenta(f"\t\tExpected value equal to {expected}")
|
|
41
|
+
printMagenta(f"\t\tValue equal to {testValue}")
|
|
42
|
+
|
|
43
|
+
def testIfNotEqual(self, expected, testValue, message):
|
|
44
|
+
response = self.testIftrue(expected != testValue, message)
|
|
45
|
+
if response == 2:
|
|
46
|
+
printMagenta(f"\t\tExpected value differen to {expected}")
|
|
47
|
+
printMagenta(f"\t\tValue equal to {testValue}")
|
|
48
|
+
|
|
49
|
+
def testIfGreater(self, expected, testValue, message):
|
|
50
|
+
response = self.testIftrue(expected > testValue, message)
|
|
51
|
+
if response == 2:
|
|
52
|
+
printMagenta(f"\t\tExpected value greater than {expected}")
|
|
53
|
+
printMagenta(f"\t\tValue equal to {testValue}")
|
|
54
|
+
|
|
55
|
+
def testIfGreaterEqual(self, expected, testValue, message):
|
|
56
|
+
response = self.testIftrue(expected >= testValue, message)
|
|
57
|
+
if response == 2:
|
|
58
|
+
printMagenta(f"\t\tExpected value greater or equal than {expected}")
|
|
59
|
+
printMagenta(f"\t\tValue equal to {testValue}")
|
|
60
|
+
|
|
61
|
+
def testIfLess(self, expected, testValue, message):
|
|
62
|
+
response = self.testIftrue(expected < testValue, message)
|
|
63
|
+
if response == 2:
|
|
64
|
+
printMagenta(f"\t\tExpected value less than {expected}")
|
|
65
|
+
printMagenta(f"\t\tValue equal to {testValue}")
|
|
66
|
+
|
|
67
|
+
def testIfLessEqual(self, expected, testValue, message):
|
|
68
|
+
response = self.testIftrue(expected <= testValue, message)
|
|
69
|
+
if response == 2:
|
|
70
|
+
printMagenta(f"\t\tExpected value less or equal than {expected}")
|
|
71
|
+
printMagenta(f"\t\tValue equal to {testValue}")
|
|
72
|
+
|
|
73
|
+
def newScenario(self, name):
|
|
74
|
+
self.scenarioCount += 1
|
|
75
|
+
print(f"Starting scenario {self.scenarioCount}: {name}")
|
|
76
|
+
|
|
77
|
+
def endScenario(self, name):
|
|
78
|
+
if self.escenarioPassed:
|
|
79
|
+
print(f"Scenario {self.scenarioCount}:{name} ended with result: PASSED")
|
|
80
|
+
else:
|
|
81
|
+
print(f"Scenario {self.scenarioCount}:{name} ended with result: FAILED")
|
|
82
|
+
if self.escenarioFailed:
|
|
83
|
+
self.passed = False
|
|
84
|
+
self.failed = True
|
|
85
|
+
self.escenarioPassed = True
|
|
86
|
+
self.escenarioFailed = False
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# Output test results in different ways
|
|
90
|
+
def printResults(self):
|
|
91
|
+
if self.passed:
|
|
92
|
+
printGreenBold("TEST PASSED")
|
|
93
|
+
else:
|
|
94
|
+
printRedBold("TEST FAILED")
|
|
95
|
+
print(f"\t {self.scenarioCount} scenarios")
|
|
96
|
+
print(f"\t {self.testCount} tests")
|
|
97
|
+
print(f"\t {self.passCount} passed")
|
|
98
|
+
print(f"\t {self.failCount} failed")
|
|
99
|
+
print(f"\t {self.skipCount} skipped")
|
|
100
|
+
|
|
101
|
+
def lofResults(self, log):
|
|
102
|
+
if self.passed:
|
|
103
|
+
logger.addEntry("TEST PASSED", log.INFO_MASK)
|
|
104
|
+
else:
|
|
105
|
+
logger.addEntry("TEST FAILED", log.ERROR_MASK)
|
|
106
|
+
logger.addEntry(f"\t {self.passCount} passed\n")
|
|
107
|
+
logger.addEntry(f"\t {self.failCount} failed\n")
|
|
108
|
+
logger.addEntry(f"\t {self.skipCount} skipped\n")
|
|
109
|
+
logger.addEntry(f"\t {self.testCount} total\n")
|
|
110
|
+
|
|
111
|
+
test = testEngine()
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "articlib"
|
|
3
|
+
version = "0.2.1"
|
|
4
|
+
description = "Small set of tools and utilities in python. Destined to be use in my personal projects."
|
|
5
|
+
authors = ["Artic42 <engineer@artic42.com>"]
|
|
6
|
+
license = "MIT"
|
|
7
|
+
readme = "README.md"
|
|
8
|
+
|
|
9
|
+
[tool.poetry.dependencies]
|
|
10
|
+
python = "^3.10"
|
|
11
|
+
colorama = "^0.4.6"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
[build-system]
|
|
15
|
+
requires = ["poetry-core"]
|
|
16
|
+
build-backend = "poetry.core.masonry.api"
|