diff --git a/.gitignore b/.gitignore index 19c7901..d13a43a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ -config.toml +*config.toml *.json -__pycache__/ \ No newline at end of file +__pycache__/ +*.log \ No newline at end of file diff --git a/config.toml.example b/config.toml.example index 866b29b..e0a651b 100644 --- a/config.toml.example +++ b/config.toml.example @@ -10,4 +10,6 @@ query = "SELECT [Id],[Version] FROM [EFTDB].[dbo].[tbl_Schema_Version]" filename ="./data.json" [logging] -use_log = true \ No newline at end of file +use_log = true +logLevel = "debug" +logPath = "./inex.log" \ No newline at end of file diff --git a/executable/config.toml.example b/executable/config.toml.example new file mode 100644 index 0000000..e0a651b --- /dev/null +++ b/executable/config.toml.example @@ -0,0 +1,15 @@ +[database] +driver = "ODBC Driver 18 for SQL Server" +server = "192.168.x.x" +database = "EFTDB" +user = "a" +password = "a" +query = "SELECT [Id],[Version] FROM [EFTDB].[dbo].[tbl_Schema_Version]" + +[output] +filename ="./data.json" + +[logging] +use_log = true +logLevel = "debug" +logPath = "./inex.log" \ No newline at end of file diff --git a/executable/inex.exe b/executable/inex.exe new file mode 100644 index 0000000..7a9e7bc Binary files /dev/null and b/executable/inex.exe differ diff --git a/inex.py b/inex.py index 04e4340..047b722 100644 --- a/inex.py +++ b/inex.py @@ -1,9 +1,10 @@ import pandas import pyodbc import os +import logging import datetime from tomllib import load -import inexLogging +from inexLogging import inexLog import inexConnect import json import decimal @@ -20,7 +21,7 @@ class Inex: self.pd = pandas self.db = pyodbc self.tm = datetime - self.il = inexLogging + self.il = logging self.ic = inexConnect # set config @@ -31,17 +32,28 @@ class Inex: self.dbPassword = self.config["database"]["password"] self.dbQuery = self.config["database"]["query"] self.outputFile = self.config["output"]["filename"] + self.useLog = self.config["logging"]["useLog"] + self.logPath = self.config["logging"]["logPath"] + self.logLevel = self.config["logging"]["logLevel"] + + #Setup logging + inexLog(self) # create the connection to the database - self.cursor = self.ic.connectDatabase(self.db, self.dbDriver, self.dbServer, self.dbDatabase, self.dbUser, self.dbPassword) + self.cursor = self.ic.connectDatabase(self, self.db, self.dbDriver, self.dbServer, self.dbDatabase, self.dbUser, self.dbPassword) - self.data = self.ic.databaseQuery(self.cursor, self.dbQuery) + self.data = self.ic.databaseQuery(self, self.cursor, self.dbQuery) # print(self.data) + # TODO: move this to its own function + if self.useLog: + self.il.warning(f"Writing to '{self.outputFile}'.") + with open(self.outputFile, "w") as f: json.dump(self.data, f, cls=Encoder) +# TODO: Move this class to it's own file class Encoder(json.JSONEncoder): def default(self, o): if isinstance(o, decimal.Decimal): diff --git a/inexConnect.py b/inexConnect.py index b87a05a..b881f4a 100644 --- a/inexConnect.py +++ b/inexConnect.py @@ -1,13 +1,42 @@ -def connectDatabase(lib, driver, server, database, user, password): +def connectDatabase(self, lib, driver, server, database, user, password): + """Connects to the database. Requires a windows driver to do so. + Typically there is one installed by default""" + connectionString = f'DRIVER={{{driver}}};SERVER={server};DATABASE={database};UID={user};PWD={password};TrustServerCertificate=yes' - print(connectionString) - connection = lib.connect(connectionString) + if self.useLog: + self.il.debug(f"Connection String: connectionString") + self.il.info(f"Connecting to {database}@{server} with driver[{driver}].") + try: + connection = lib.connect(connectionString) + except lib.Error as ex: + sqlstate = ex.args[1] + if self.useLog: + self.il.error(sqlstate) + if self.useLog: + self.il.debug(f"Connected.") cursor = connection.cursor() + return cursor -def databaseQuery(cursor, query, args=(), one=False): - cur = cursor.execute(query, args) +def databaseQuery(self, cursor, query, args=(), one=False): + if self.useLog: + self.il.debug(f"Query:") + self.il.debug(query) + self.il.info(f"Sending query:{query[0:20]}...") + + try: + cur = cursor.execute(query, args) + except cur.Error as ex: + sqlstate = ex.args[1] + if self.useLog: + self.il.error(sqlstate) + + if self.useLog: + self.il.debug(f"Processing database response...") r = [dict((cur.description[i][0], value) \ for i, value in enumerate(row)) for row in cur.fetchall()] + cur.connection.close() + if self.useLog: + self.il.debug(f"Databse connection closed") return (r[0] if r else None) if one else r \ No newline at end of file diff --git a/inexLogging.py b/inexLogging.py index e69de29..32d5c7e 100644 --- a/inexLogging.py +++ b/inexLogging.py @@ -0,0 +1,11 @@ +def inexLog(self): + """Setting up the log file, if self.useLog is set to true and self.logLevel is DEBUG, INFO, WARNING or ERROR""" + if self.useLog: + if self.logLevel.lower() == 'debug': + self.il.basicConfig(filename=self.logPath, format='%(asctime)s:%(levelname)s:%(message)s', encoding='utf-8', datefmt='%m/%d/%Y %I:%M:%S %p',level=self.il.DEBUG) + elif self.logLevel.lower() == 'info': + self.il.basicConfig(filename=self.logPath, format='%(asctime)s:%(levelname)s:%(message)s', encoding='utf-8', datefmt='%m/%d/%Y %I:%M:%S %p',level=self.il.INFO) + elif self.logLevel.lower() == 'warning': + self.il.basicConfig(filename=self.logPath, format='%(asctime)s:%(levelname)s:%(message)s', encoding='utf-8', datefmt='%m/%d/%Y %I:%M:%S %p',level=self.il.WARNING) + elif self.logLevel.lower() == 'error': + self.il.basicConfig(filename=self.logPath, format='%(asctime)s:%(levelname)s:%(message)s', encoding='utf-8', datefmt='%m/%d/%Y %I:%M:%S %p',level=self.il.ERROR) \ No newline at end of file