diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2483976 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea/ +__pycache__/ diff --git a/Package_Measurement_Conversion_API/Logging/error_log.log b/Package_Measurement_Conversion_API/Logging/error_log.log new file mode 100644 index 0000000..d6730a7 --- /dev/null +++ b/Package_Measurement_Conversion_API/Logging/error_log.log @@ -0,0 +1,252 @@ +2024-05-01 10:45:50,257:INFO:[01/May/2024:10:45:50] ENGINE Listening for SIGTERM. +2024-05-01 10:45:50,257:INFO:[01/May/2024:10:45:50] ENGINE Bus STARTING +2024-05-01 10:45:50,257:INFO:[01/May/2024:10:45:50] ENGINE Started monitor thread 'Autoreloader'. +2024-05-01 10:45:50,491:INFO:[01/May/2024:10:45:50] ENGINE Serving on http://127.0.0.1:8080 +2024-05-01 10:45:50,491:INFO:[01/May/2024:10:45:50] ENGINE Bus STARTED +2024-05-01 10:45:55,758:INFO:127.0.0.1 - - [01/May/2024:10:45:55] "GET /conversion_results?input_string=abbcc HTTP/1.1" 200 6 "" "PostmanRuntime/7.37.3" +2024-05-01 10:46:10,457:INFO:[01/May/2024:10:46:10] ENGINE Keyboard Interrupt: shutting down bus +2024-05-01 10:46:10,464:INFO:[01/May/2024:10:46:10] ENGINE Bus STOPPING +2024-05-01 10:46:10,607:INFO:[01/May/2024:10:46:10] ENGINE HTTP Server cherrypy._cpwsgi_server.CPWSGIServer(('127.0.0.1', 8080)) shut down +2024-05-01 10:46:10,607:INFO:[01/May/2024:10:46:10] ENGINE Stopped thread 'Autoreloader'. +2024-05-01 10:46:10,607:INFO:[01/May/2024:10:46:10] ENGINE Bus STOPPED +2024-05-01 10:46:10,607:INFO:[01/May/2024:10:46:10] ENGINE Bus EXITING +2024-05-01 10:46:10,607:INFO:[01/May/2024:10:46:10] ENGINE Bus EXITED +2024-05-01 10:46:10,607:INFO:[01/May/2024:10:46:10] ENGINE Waiting for child threads to terminate... +2024-05-01 10:48:21,501:INFO:[01/May/2024:10:48:21] ENGINE Listening for SIGTERM. +2024-05-01 10:48:21,501:INFO:[01/May/2024:10:48:21] ENGINE Bus STARTING +2024-05-01 10:48:21,502:INFO:[01/May/2024:10:48:21] ENGINE Started monitor thread 'Autoreloader'. +2024-05-01 10:48:21,736:INFO:[01/May/2024:10:48:21] ENGINE Serving on http://127.0.0.1:8080 +2024-05-01 10:48:21,736:INFO:[01/May/2024:10:48:21] ENGINE Bus STARTED +2024-05-01 10:48:26,933:INFO:127.0.0.1 - - [01/May/2024:10:48:26] "GET /conversion_results?input_string=abbcc HTTP/1.1" 200 6 "" "PostmanRuntime/7.37.3" +2024-05-01 10:52:19,637:INFO:[01/May/2024:10:52:19] ENGINE Keyboard Interrupt: shutting down bus +2024-05-01 10:52:19,637:INFO:[01/May/2024:10:52:19] ENGINE Bus STOPPING +2024-05-01 10:52:19,820:INFO:[01/May/2024:10:52:19] ENGINE HTTP Server cherrypy._cpwsgi_server.CPWSGIServer(('127.0.0.1', 8080)) shut down +2024-05-01 10:52:19,820:INFO:[01/May/2024:10:52:19] ENGINE Stopped thread 'Autoreloader'. +2024-05-01 10:52:19,820:INFO:[01/May/2024:10:52:19] ENGINE Bus STOPPED +2024-05-01 10:52:19,821:INFO:[01/May/2024:10:52:19] ENGINE Bus EXITING +2024-05-01 10:52:19,821:INFO:[01/May/2024:10:52:19] ENGINE Bus EXITED +2024-05-01 10:52:19,821:INFO:[01/May/2024:10:52:19] ENGINE Waiting for child threads to terminate... +2024-05-02 08:56:40,484:INFO:[02/May/2024:08:56:40] ENGINE Listening for SIGTERM. +2024-05-02 08:56:40,485:INFO:[02/May/2024:08:56:40] ENGINE Bus STARTING +2024-05-02 08:56:40,486:INFO:[02/May/2024:08:56:40] ENGINE Started monitor thread 'Autoreloader'. +2024-05-02 08:56:40,705:INFO:[02/May/2024:08:56:40] ENGINE Serving on http://127.0.0.1:8080 +2024-05-02 08:56:40,705:INFO:[02/May/2024:08:56:40] ENGINE Bus STARTED +2024-05-02 08:56:46,358:INFO:127.0.0.1 - - [02/May/2024:08:56:46] "GET /conversion_results?input_string=abbcc HTTP/1.1" 200 105 "" "PostmanRuntime/7.37.3" +2024-05-02 08:57:00,053:INFO:[02/May/2024:08:57:00] ENGINE Keyboard Interrupt: shutting down bus +2024-05-02 08:57:00,053:INFO:[02/May/2024:08:57:00] ENGINE Bus STOPPING +2024-05-02 08:57:00,207:INFO:[02/May/2024:08:57:00] ENGINE HTTP Server cherrypy._cpwsgi_server.CPWSGIServer(('127.0.0.1', 8080)) shut down +2024-05-02 08:57:00,208:INFO:[02/May/2024:08:57:00] ENGINE Stopped thread 'Autoreloader'. +2024-05-02 08:57:00,208:INFO:[02/May/2024:08:57:00] ENGINE Bus STOPPED +2024-05-02 08:57:00,208:INFO:[02/May/2024:08:57:00] ENGINE Bus EXITING +2024-05-02 08:57:00,208:INFO:[02/May/2024:08:57:00] ENGINE Bus EXITED +2024-05-02 08:57:00,208:INFO:[02/May/2024:08:57:00] ENGINE Waiting for child threads to terminate... +2024-05-02 08:57:29,296:INFO:[02/May/2024:08:57:29] ENGINE Listening for SIGTERM. +2024-05-02 08:57:29,296:INFO:[02/May/2024:08:57:29] ENGINE Bus STARTING +2024-05-02 08:57:29,298:INFO:[02/May/2024:08:57:29] ENGINE Started monitor thread 'Autoreloader'. +2024-05-02 08:57:29,524:INFO:[02/May/2024:08:57:29] ENGINE Serving on http://127.0.0.1:8080 +2024-05-02 08:57:29,524:INFO:[02/May/2024:08:57:29] ENGINE Bus STARTED +2024-05-02 08:57:32,810:INFO:127.0.0.1 - - [02/May/2024:08:57:32] "GET /conversion_results?input_string=abbcc HTTP/1.1" 200 54 "" "PostmanRuntime/7.37.3" +2024-05-02 08:59:15,892:INFO:[02/May/2024:08:59:15] ENGINE Keyboard Interrupt: shutting down bus +2024-05-02 08:59:15,892:INFO:[02/May/2024:08:59:15] ENGINE Bus STOPPING +2024-05-02 08:59:16,029:INFO:[02/May/2024:08:59:16] ENGINE HTTP Server cherrypy._cpwsgi_server.CPWSGIServer(('127.0.0.1', 8080)) shut down +2024-05-02 08:59:16,029:INFO:[02/May/2024:08:59:16] ENGINE Stopped thread 'Autoreloader'. +2024-05-02 08:59:16,029:INFO:[02/May/2024:08:59:16] ENGINE Bus STOPPED +2024-05-02 08:59:16,029:INFO:[02/May/2024:08:59:16] ENGINE Bus EXITING +2024-05-02 08:59:16,029:INFO:[02/May/2024:08:59:16] ENGINE Bus EXITED +2024-05-02 08:59:16,029:INFO:[02/May/2024:08:59:16] ENGINE Waiting for child threads to terminate... +2024-05-02 09:15:13,242:INFO:[02/May/2024:09:15:13] ENGINE Listening for SIGTERM. +2024-05-02 09:15:13,242:INFO:[02/May/2024:09:15:13] ENGINE Bus STARTING +2024-05-02 09:15:13,244:INFO:[02/May/2024:09:15:13] ENGINE Started monitor thread 'Autoreloader'. +2024-05-02 09:15:13,458:INFO:[02/May/2024:09:15:13] ENGINE Serving on http://127.0.0.1:8080 +2024-05-02 09:15:13,459:INFO:[02/May/2024:09:15:13] ENGINE Bus STARTED +2024-05-02 09:15:21,563:INFO:127.0.0.1 - - [02/May/2024:09:15:21] "GET /conversion_results?input_string=aaa HTTP/1.1" 200 51 "" "PostmanRuntime/7.37.3" +2024-05-02 09:15:32,386:INFO:127.0.0.1 - - [02/May/2024:09:15:32] "GET /conversion_results?input_string=ccc HTTP/1.1" 200 50 "" "PostmanRuntime/7.37.3" +2024-05-02 09:15:38,316:INFO:[02/May/2024:09:15:38] ENGINE Keyboard Interrupt: shutting down bus +2024-05-02 09:15:38,316:INFO:[02/May/2024:09:15:38] ENGINE Bus STOPPING +2024-05-02 09:15:38,442:INFO:[02/May/2024:09:15:38] ENGINE HTTP Server cherrypy._cpwsgi_server.CPWSGIServer(('127.0.0.1', 8080)) shut down +2024-05-02 09:15:38,442:INFO:[02/May/2024:09:15:38] ENGINE Stopped thread 'Autoreloader'. +2024-05-02 09:15:38,442:INFO:[02/May/2024:09:15:38] ENGINE Bus STOPPED +2024-05-02 09:15:38,442:INFO:[02/May/2024:09:15:38] ENGINE Bus EXITING +2024-05-02 09:15:38,442:INFO:[02/May/2024:09:15:38] ENGINE Bus EXITED +2024-05-02 09:15:38,442:INFO:[02/May/2024:09:15:38] ENGINE Waiting for child threads to terminate... +2024-05-02 09:16:27,257:INFO:[02/May/2024:09:16:27] ENGINE Listening for SIGTERM. +2024-05-02 09:16:27,257:INFO:[02/May/2024:09:16:27] ENGINE Bus STARTING +2024-05-02 09:16:27,257:INFO:[02/May/2024:09:16:27] ENGINE Started monitor thread 'Autoreloader'. +2024-05-02 09:16:27,472:INFO:[02/May/2024:09:16:27] ENGINE Serving on http://127.0.0.1:8080 +2024-05-02 09:16:27,472:INFO:[02/May/2024:09:16:27] ENGINE Bus STARTED +2024-05-02 09:16:35,576:INFO:127.0.0.1 - - [02/May/2024:09:16:35] "GET /conversion_results?input_string=aaa HTTP/1.1" 200 51 "" "PostmanRuntime/7.37.3" +2024-05-02 09:21:06,348:INFO:[02/May/2024:09:21:06] ENGINE Keyboard Interrupt: shutting down bus +2024-05-02 09:21:06,348:INFO:[02/May/2024:09:21:06] ENGINE Bus STOPPING +2024-05-02 09:21:06,487:INFO:[02/May/2024:09:21:06] ENGINE HTTP Server cherrypy._cpwsgi_server.CPWSGIServer(('127.0.0.1', 8080)) shut down +2024-05-02 09:21:06,487:INFO:[02/May/2024:09:21:06] ENGINE Stopped thread 'Autoreloader'. +2024-05-02 09:21:06,487:INFO:[02/May/2024:09:21:06] ENGINE Bus STOPPED +2024-05-02 09:21:06,487:INFO:[02/May/2024:09:21:06] ENGINE Bus EXITING +2024-05-02 09:21:06,487:INFO:[02/May/2024:09:21:06] ENGINE Bus EXITED +2024-05-02 09:21:06,487:INFO:[02/May/2024:09:21:06] ENGINE Waiting for child threads to terminate... +2024-05-02 09:52:03,005:INFO:[02/May/2024:09:52:03] ENGINE Listening for SIGTERM. +2024-05-02 09:52:03,005:INFO:[02/May/2024:09:52:03] ENGINE Bus STARTING +2024-05-02 09:52:03,005:INFO:[02/May/2024:09:52:03] ENGINE Started monitor thread 'Autoreloader'. +2024-05-02 09:52:03,232:INFO:[02/May/2024:09:52:03] ENGINE Serving on http://127.0.0.1:8080 +2024-05-02 09:52:03,232:INFO:[02/May/2024:09:52:03] ENGINE Bus STARTED +2024-05-02 09:52:52,484:INFO:127.0.0.1 - - [02/May/2024:09:52:52] "GET /conversion_results?input_string=aaa HTTP/1.1" 200 50 "" "PostmanRuntime/7.37.3" +2024-05-02 09:52:55,695:INFO:127.0.0.1 - - [02/May/2024:09:52:55] "GET /conversion_results?input_string=aa HTTP/1.1" 200 51 "" "PostmanRuntime/7.37.3" +2024-05-02 09:55:18,666:INFO:[02/May/2024:09:55:18] ENGINE Keyboard Interrupt: shutting down bus +2024-05-02 09:55:18,666:INFO:[02/May/2024:09:55:18] ENGINE Bus STOPPING +2024-05-02 09:55:18,786:INFO:[02/May/2024:09:55:18] ENGINE HTTP Server cherrypy._cpwsgi_server.CPWSGIServer(('127.0.0.1', 8080)) shut down +2024-05-02 09:55:18,786:INFO:[02/May/2024:09:55:18] ENGINE Stopped thread 'Autoreloader'. +2024-05-02 09:55:18,786:INFO:[02/May/2024:09:55:18] ENGINE Bus STOPPED +2024-05-02 09:55:18,786:INFO:[02/May/2024:09:55:18] ENGINE Bus EXITING +2024-05-02 09:55:18,786:INFO:[02/May/2024:09:55:18] ENGINE Bus EXITED +2024-05-02 09:55:18,786:INFO:[02/May/2024:09:55:18] ENGINE Waiting for child threads to terminate... +2024-05-02 09:55:19,770:INFO:[02/May/2024:09:55:19] ENGINE Listening for SIGTERM. +2024-05-02 09:55:19,770:INFO:[02/May/2024:09:55:19] ENGINE Bus STARTING +2024-05-02 09:55:19,771:INFO:[02/May/2024:09:55:19] ENGINE Started monitor thread 'Autoreloader'. +2024-05-02 09:55:19,991:INFO:[02/May/2024:09:55:19] ENGINE Serving on http://0.0.0.0:8080 +2024-05-02 09:55:19,991:INFO:[02/May/2024:09:55:19] ENGINE Bus STARTED +2024-05-02 09:55:23,093:INFO:192.168.137.1 - - [02/May/2024:09:55:23] "GET / HTTP/1.1" 404 1518 "" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" +2024-05-02 09:55:23,277:INFO:192.168.137.1 - - [02/May/2024:09:55:23] "GET /favicon.ico HTTP/1.1" 200 1406 "http://192.168.137.86:8080/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" +2024-05-02 09:55:51,855:INFO:192.168.137.1 - - [02/May/2024:09:55:51] "GET /conversion_results?input_string=aa HTTP/1.1" 200 51 "" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" +2024-05-02 09:56:50,085:INFO:192.168.137.1 - - [02/May/2024:09:56:50] "GET /conversion_results?input_string=aa HTTP/1.1" 200 51 "" "python-requests/2.31.0" +2024-05-02 09:56:50,102:INFO:192.168.137.1 - - [02/May/2024:09:56:50] "GET /conversion_results?input_string=abbcc HTTP/1.1" 200 51 "" "python-requests/2.31.0" +2024-05-02 09:56:50,116:INFO:192.168.137.1 - - [02/May/2024:09:56:50] "GET /conversion_results?input_string=dz_a_aazzaaa HTTP/1.1" 200 51 "" "python-requests/2.31.0" +2024-05-02 09:56:50,132:INFO:192.168.137.1 - - [02/May/2024:09:56:50] "GET /conversion_results?input_string=a_ HTTP/1.1" 200 51 "" "python-requests/2.31.0" +2024-05-02 09:56:50,145:INFO:192.168.137.1 - - [02/May/2024:09:56:50] "GET /conversion_results?input_string=abcdabcdab HTTP/1.1" 200 51 "" "python-requests/2.31.0" +2024-05-02 09:56:50,156:INFO:192.168.137.1 - - [02/May/2024:09:56:50] "GET /conversion_results?input_string=abcdabcdab_ HTTP/1.1" 200 60 "" "python-requests/2.31.0" +2024-05-02 09:56:50,168:INFO:192.168.137.1 - - [02/May/2024:09:56:50] "GET /conversion_results?input_string=zdaaaaaaaabaaaaaaaabaaaaaaaabbaa HTTP/1.1" 200 52 "" "python-requests/2.31.0" +2024-05-02 09:56:50,178:INFO:192.168.137.1 - - [02/May/2024:09:56:50] "GET /conversion_results?input_string=zza_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_ HTTP/1.1" 200 52 "" "python-requests/2.31.0" +2024-05-02 09:56:50,230:INFO:192.168.137.1 - - [02/May/2024:09:56:50] "GET /conversion_results?input_string=za_a_a_a_a_a_a_a_a_a_a_a_a_azaaa HTTP/1.1" 200 51 "" "python-requests/2.31.0" +2024-05-02 09:56:50,312:INFO:192.168.137.1 - - [02/May/2024:09:56:50] "GET /conversion_results?input_string=_ HTTP/1.1" 200 51 "" "python-requests/2.31.0" +2024-05-02 09:56:50,325:INFO:192.168.137.1 - - [02/May/2024:09:56:50] "GET /conversion_results?input_string=_ad HTTP/1.1" 200 51 "" "python-requests/2.31.0" +2024-05-02 09:56:50,344:INFO:192.168.137.1 - - [02/May/2024:09:56:50] "GET /conversion_results?input_string=a_ HTTP/1.1" 200 51 "" "python-requests/2.31.0" +2024-05-02 09:56:50,380:INFO:192.168.137.1 - - [02/May/2024:09:56:50] "GET /conversion_results?input_string=_zzzb HTTP/1.1" 200 51 "" "python-requests/2.31.0" +2024-05-02 09:56:50,392:INFO:192.168.137.1 - - [02/May/2024:09:56:50] "GET /conversion_results?input_string=__ HTTP/1.1" 200 51 "" "python-requests/2.31.0" +2024-05-02 09:56:50,406:INFO:192.168.137.1 - - [02/May/2024:09:56:50] "GET /conversion_results?input_string=+++ HTTP/1.1" 200 50 "" "python-requests/2.31.0" +2024-05-02 09:56:50,443:INFO:192.168.137.1 - - [02/May/2024:09:56:50] "GET /conversion_results?input_string=%40%40%40 HTTP/1.1" 200 50 "" "python-requests/2.31.0" +2024-05-02 09:56:50,493:INFO:192.168.137.1 - - [02/May/2024:09:56:50] "GET /conversion_results?input_string=1234 HTTP/1.1" 200 50 "" "python-requests/2.31.0" +2024-05-02 09:56:50,514:INFO:192.168.137.1 - - [02/May/2024:09:56:50] "GET /conversion_results?input_string=aaa HTTP/1.1" 200 50 "" "python-requests/2.31.0" +2024-05-02 09:56:50,526:INFO:192.168.137.1 - - [02/May/2024:09:56:50] "GET /conversion_results?input_string=ccc HTTP/1.1" 200 50 "" "python-requests/2.31.0" +2024-05-02 09:58:34,143:INFO:192.168.137.86 - - [02/May/2024:09:58:34] "GET /conversion_results?input_string=bbcc HTTP/1.1" 200 50 "" "PostmanRuntime/7.37.3" +2024-05-02 09:58:37,152:INFO:192.168.137.86 - - [02/May/2024:09:58:37] "GET /conversion_results?input_string=abbcc HTTP/1.1" 200 51 "" "PostmanRuntime/7.37.3" +2024-05-02 09:59:12,668:INFO:[02/May/2024:09:59:12] ENGINE Restarting because C:\Users\71538\Documents\PackageMeasurementConversionAPI\Package_Measurement_Conversion_API\services\converter.py changed. +2024-05-02 09:59:12,669:INFO:[02/May/2024:09:59:12] ENGINE Stopped thread 'Autoreloader'. +2024-05-02 09:59:12,669:INFO:[02/May/2024:09:59:12] ENGINE Bus STOPPING +2024-05-02 09:59:12,810:INFO:[02/May/2024:09:59:12] ENGINE HTTP Server cherrypy._cpwsgi_server.CPWSGIServer(('0.0.0.0', 8080)) shut down +2024-05-02 09:59:12,810:INFO:[02/May/2024:09:59:12] ENGINE Bus STOPPED +2024-05-02 09:59:12,811:INFO:[02/May/2024:09:59:12] ENGINE Bus EXITING +2024-05-02 09:59:12,811:INFO:[02/May/2024:09:59:12] ENGINE Bus EXITED +2024-05-02 09:59:12,899:INFO:[02/May/2024:09:59:12] ENGINE Waiting for child threads to terminate... +2024-05-02 09:59:12,899:INFO:[02/May/2024:09:59:12] ENGINE Re-spawning C:\Users\71538\AppData\Local\Programs\Python\Python312\python.exe C:\Users\71538\Documents\PackageMeasurementConversionAPI\main_app.py +2024-05-02 09:59:13,383:INFO:[02/May/2024:09:59:13] ENGINE Listening for SIGTERM. +2024-05-02 09:59:13,405:INFO:[02/May/2024:09:59:13] ENGINE Bus STARTING +2024-05-02 09:59:13,405:INFO:[02/May/2024:09:59:13] ENGINE Started monitor thread 'Autoreloader'. +2024-05-02 09:59:13,638:INFO:[02/May/2024:09:59:13] ENGINE Serving on http://0.0.0.0:8080 +2024-05-02 09:59:13,638:INFO:[02/May/2024:09:59:13] ENGINE Bus STARTED +2024-05-02 09:59:17,768:INFO:[02/May/2024:09:59:17] ENGINE Listening for SIGTERM. +2024-05-02 09:59:17,768:INFO:[02/May/2024:09:59:17] ENGINE Bus STARTING +2024-05-02 09:59:17,769:INFO:[02/May/2024:09:59:17] ENGINE Started monitor thread 'Autoreloader'. +2024-05-02 09:59:18,956:ERROR:[02/May/2024:09:59:18] ENGINE Error in 'start' listener > +Traceback (most recent call last): + File "C:\Users\71538\AppData\Roaming\Python\Python312\site-packages\portend.py", line 122, in free + Checker(timeout=0.1).assert_free(host, port) + File "C:\Users\71538\AppData\Roaming\Python\Python312\site-packages\portend.py", line 71, in assert_free + list(itertools.starmap(self._connect, info)) + File "C:\Users\71538\AppData\Roaming\Python\Python312\site-packages\portend.py", line 87, in _connect + raise PortNotFree(tmpl.format(**locals())) +portend.PortNotFree: Port 8080 is in use on 127.0.0.1. + +During handling of the above exception, another exception occurred: + +Traceback (most recent call last): + File "C:\Users\71538\AppData\Roaming\Python\Python312\site-packages\cherrypy\process\wspbus.py", line 230, in publish + output.append(listener(*args, **kwargs)) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\71538\AppData\Roaming\Python\Python312\site-packages\cherrypy\_cpserver.py", line 180, in start + super(Server, self).start() + File "C:\Users\71538\AppData\Roaming\Python\Python312\site-packages\cherrypy\process\servers.py", line 177, in start + portend.free(*self.bind_addr, timeout=Timeouts.free) + File "C:\Users\71538\AppData\Roaming\Python\Python312\site-packages\portend.py", line 126, in free + raise Timeout("Port {port} not free on {host}.".format(**locals())) +portend.Timeout: Port 8080 not free on 0.0.0.0. + +2024-05-02 09:59:18,957:ERROR:[02/May/2024:09:59:18] ENGINE Shutting down due to error in start listener: +Traceback (most recent call last): + File "C:\Users\71538\AppData\Roaming\Python\Python312\site-packages\cherrypy\process\wspbus.py", line 268, in start + self.publish('start') + File "C:\Users\71538\AppData\Roaming\Python\Python312\site-packages\cherrypy\process\wspbus.py", line 248, in publish + raise exc +cherrypy.process.wspbus.ChannelFailures: Timeout('Port 8080 not free on 0.0.0.0.') + +2024-05-02 09:59:18,957:INFO:[02/May/2024:09:59:18] ENGINE Bus STOPPING +2024-05-02 09:59:18,957:INFO:[02/May/2024:09:59:18] ENGINE HTTP Server cherrypy._cpwsgi_server.CPWSGIServer(('0.0.0.0', 8080)) already shut down +2024-05-02 09:59:18,957:INFO:[02/May/2024:09:59:18] ENGINE Stopped thread 'Autoreloader'. +2024-05-02 09:59:18,957:INFO:[02/May/2024:09:59:18] ENGINE Bus STOPPED +2024-05-02 09:59:18,957:INFO:[02/May/2024:09:59:18] ENGINE Bus EXITING +2024-05-02 09:59:18,957:INFO:[02/May/2024:09:59:18] ENGINE Bus EXITED +2024-05-02 09:59:20,486:INFO:192.168.137.86 - - [02/May/2024:09:59:20] "GET /conversion_results?input_string=abbcc HTTP/1.1" 200 54 "" "PostmanRuntime/7.37.3" +2024-05-02 09:59:48,401:INFO:192.168.137.86 - - [02/May/2024:09:59:48] "GET /conversion_results?input_string=dz_a_aazzaaa HTTP/1.1" 200 59 "" "PostmanRuntime/7.37.3" +2024-05-02 10:00:10,299:INFO:192.168.137.86 - - [02/May/2024:10:00:10] "GET /conversion_results?input_string=abcdabcdab HTTP/1.1" 200 57 "" "PostmanRuntime/7.37.3" +2024-05-02 10:00:30,686:INFO:192.168.137.86 - - [02/May/2024:10:00:30] "GET /conversion_results?input_string= HTTP/1.1" 200 50 "" "PostmanRuntime/7.37.3" +2024-05-02 10:00:33,663:INFO:192.168.137.86 - - [02/May/2024:10:00:33] "GET /conversion_results?input_string=__ HTTP/1.1" 200 51 "" "PostmanRuntime/7.37.3" +2024-05-02 10:00:48,954:INFO:192.168.137.86 - - [02/May/2024:10:00:48] "GET /conversion_results?input_string=@@@ HTTP/1.1" 200 50 "" "PostmanRuntime/7.37.3" +2024-05-02 10:01:02,267:INFO:192.168.137.86 - - [02/May/2024:10:01:02] "GET /conversion_results?input_string=1234 HTTP/1.1" 200 50 "" "PostmanRuntime/7.37.3" +2024-05-02 10:01:22,988:INFO:[02/May/2024:10:01:22] ENGINE Listening for SIGTERM. +2024-05-02 10:01:22,988:INFO:[02/May/2024:10:01:22] ENGINE Bus STARTING +2024-05-02 10:01:22,988:INFO:[02/May/2024:10:01:22] ENGINE Started monitor thread 'Autoreloader'. +2024-05-02 10:01:24,011:ERROR:[02/May/2024:10:01:24] ENGINE Error in 'start' listener > +Traceback (most recent call last): + File "C:\Users\71538\AppData\Roaming\Python\Python312\site-packages\portend.py", line 122, in free + Checker(timeout=0.1).assert_free(host, port) + File "C:\Users\71538\AppData\Roaming\Python\Python312\site-packages\portend.py", line 71, in assert_free + list(itertools.starmap(self._connect, info)) + File "C:\Users\71538\AppData\Roaming\Python\Python312\site-packages\portend.py", line 87, in _connect + raise PortNotFree(tmpl.format(**locals())) +portend.PortNotFree: Port 8080 is in use on 127.0.0.1. + +During handling of the above exception, another exception occurred: + +Traceback (most recent call last): + File "C:\Users\71538\AppData\Roaming\Python\Python312\site-packages\cherrypy\process\wspbus.py", line 230, in publish + output.append(listener(*args, **kwargs)) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\71538\AppData\Roaming\Python\Python312\site-packages\cherrypy\_cpserver.py", line 180, in start + super(Server, self).start() + File "C:\Users\71538\AppData\Roaming\Python\Python312\site-packages\cherrypy\process\servers.py", line 177, in start + portend.free(*self.bind_addr, timeout=Timeouts.free) + File "C:\Users\71538\AppData\Roaming\Python\Python312\site-packages\portend.py", line 126, in free + raise Timeout("Port {port} not free on {host}.".format(**locals())) +portend.Timeout: Port 8080 not free on 0.0.0.0. + +2024-05-02 10:01:24,012:ERROR:[02/May/2024:10:01:24] ENGINE Shutting down due to error in start listener: +Traceback (most recent call last): + File "C:\Users\71538\AppData\Roaming\Python\Python312\site-packages\cherrypy\process\wspbus.py", line 268, in start + self.publish('start') + File "C:\Users\71538\AppData\Roaming\Python\Python312\site-packages\cherrypy\process\wspbus.py", line 248, in publish + raise exc +cherrypy.process.wspbus.ChannelFailures: Timeout('Port 8080 not free on 0.0.0.0.') + +2024-05-02 10:01:24,012:INFO:[02/May/2024:10:01:24] ENGINE Bus STOPPING +2024-05-02 10:01:24,012:INFO:[02/May/2024:10:01:24] ENGINE HTTP Server cherrypy._cpwsgi_server.CPWSGIServer(('0.0.0.0', 8080)) already shut down +2024-05-02 10:01:24,012:INFO:[02/May/2024:10:01:24] ENGINE Stopped thread 'Autoreloader'. +2024-05-02 10:01:24,012:INFO:[02/May/2024:10:01:24] ENGINE Bus STOPPED +2024-05-02 10:01:24,012:INFO:[02/May/2024:10:01:24] ENGINE Bus EXITING +2024-05-02 10:01:24,012:INFO:[02/May/2024:10:01:24] ENGINE Bus EXITED +2024-05-02 10:01:26,797:INFO:192.168.137.1 - - [02/May/2024:10:01:26] "GET /conversion_results?input_string=aa HTTP/1.1" 200 51 "" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" +2024-05-02 10:01:40,614:INFO:192.168.137.1 - - [02/May/2024:10:01:40] "GET /conversion_results?input_string=aa HTTP/1.1" 200 51 "" "python-requests/2.31.0" +2024-05-02 10:01:40,631:INFO:192.168.137.1 - - [02/May/2024:10:01:40] "GET /conversion_results?input_string=abbcc HTTP/1.1" 200 54 "" "python-requests/2.31.0" +2024-05-02 10:01:40,647:INFO:192.168.137.1 - - [02/May/2024:10:01:40] "GET /conversion_results?input_string=dz_a_aazzaaa HTTP/1.1" 200 59 "" "python-requests/2.31.0" +2024-05-02 10:01:40,661:INFO:192.168.137.1 - - [02/May/2024:10:01:40] "GET /conversion_results?input_string=a_ HTTP/1.1" 200 51 "" "python-requests/2.31.0" +2024-05-02 10:01:40,672:INFO:192.168.137.1 - - [02/May/2024:10:01:40] "GET /conversion_results?input_string=abcdabcdab HTTP/1.1" 200 57 "" "python-requests/2.31.0" +2024-05-02 10:01:40,680:INFO:192.168.137.1 - - [02/May/2024:10:01:40] "GET /conversion_results?input_string=abcdabcdab_ HTTP/1.1" 200 60 "" "python-requests/2.31.0" +2024-05-02 10:01:40,695:INFO:192.168.137.1 - - [02/May/2024:10:01:40] "GET /conversion_results?input_string=zdaaaaaaaabaaaaaaaabaaaaaaaabbaa HTTP/1.1" 200 52 "" "python-requests/2.31.0" +2024-05-02 10:01:40,695:INFO:192.168.137.1 - - [02/May/2024:10:01:40] "GET /conversion_results?input_string=zza_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_ HTTP/1.1" 200 52 "" "python-requests/2.31.0" +2024-05-02 10:01:40,710:INFO:192.168.137.1 - - [02/May/2024:10:01:40] "GET /conversion_results?input_string=za_a_a_a_a_a_a_a_a_a_a_a_a_azaaa HTTP/1.1" 200 55 "" "python-requests/2.31.0" +2024-05-02 10:01:40,738:INFO:192.168.137.1 - - [02/May/2024:10:01:40] "GET /conversion_results?input_string=_ HTTP/1.1" 200 51 "" "python-requests/2.31.0" +2024-05-02 10:01:40,742:INFO:192.168.137.1 - - [02/May/2024:10:01:40] "GET /conversion_results?input_string=_ad HTTP/1.1" 200 51 "" "python-requests/2.31.0" +2024-05-02 10:01:40,758:INFO:192.168.137.1 - - [02/May/2024:10:01:40] "GET /conversion_results?input_string=a_ HTTP/1.1" 200 51 "" "python-requests/2.31.0" +2024-05-02 10:01:40,789:INFO:192.168.137.1 - - [02/May/2024:10:01:40] "GET /conversion_results?input_string=_zzzb HTTP/1.1" 200 51 "" "python-requests/2.31.0" +2024-05-02 10:01:40,808:INFO:192.168.137.1 - - [02/May/2024:10:01:40] "GET /conversion_results?input_string=__ HTTP/1.1" 200 51 "" "python-requests/2.31.0" +2024-05-02 10:01:40,816:INFO:192.168.137.1 - - [02/May/2024:10:01:40] "GET /conversion_results?input_string=+++ HTTP/1.1" 200 50 "" "python-requests/2.31.0" +2024-05-02 10:01:40,829:INFO:192.168.137.1 - - [02/May/2024:10:01:40] "GET /conversion_results?input_string=%40%40%40 HTTP/1.1" 200 50 "" "python-requests/2.31.0" +2024-05-02 10:01:40,836:INFO:192.168.137.1 - - [02/May/2024:10:01:40] "GET /conversion_results?input_string=1234 HTTP/1.1" 200 50 "" "python-requests/2.31.0" +2024-05-02 10:01:40,852:INFO:192.168.137.1 - - [02/May/2024:10:01:40] "GET /conversion_results?input_string=aaa HTTP/1.1" 200 51 "" "python-requests/2.31.0" +2024-05-02 10:01:40,868:INFO:192.168.137.1 - - [02/May/2024:10:01:40] "GET /conversion_results?input_string=ccc HTTP/1.1" 200 50 "" "python-requests/2.31.0" diff --git a/Package_Measurement_Conversion_API/Utilities/__init__.py b/Package_Measurement_Conversion_API/Utilities/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Package_Measurement_Conversion_API/Utilities/db.py b/Package_Measurement_Conversion_API/Utilities/db.py new file mode 100644 index 0000000..b4e4297 --- /dev/null +++ b/Package_Measurement_Conversion_API/Utilities/db.py @@ -0,0 +1,39 @@ +import sqlite3 + + +class MeasurementsDB(object): + def __init__(self, name_db='conversion_history.db'): + self.name_db = name_db + self.conn = sqlite3.connect(self.name_db, check_same_thread=False) + self.cursor = self.conn.cursor() + self.create_table() + + def create_table(self): + + # Create the table that will store the conversion history + self.cursor.execute(''' + CREATE TABLE IF NOT EXISTS conversion_history ( + id INTEGER PRIMARY KEY, + input TEXT, + output TEXT, + timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ) + ''') + self.conn.commit() + + def save_table(self, input_str, output_str): + # Save the conversion history in the table + output_str = str(output_str) + self.cursor.execute('INSERT INTO conversion_history (input, output) VALUES (?, ?)', (input_str, output_str)) + self.conn.commit() + + def display_table(self): + # Display the conversion history from the table + conversion_history = [] + self.cursor.execute("SELECT input, output FROM conversion_history ORDER BY timestamp DESC") + rows = self.cursor.fetchall() + for row in rows: + data = {'input': row[0], 'output': row[1]} + conversion_history.append(data) + # conversion_history = [{'input': row[0], 'output': row[1]} for row in rows] + return conversion_history diff --git a/Package_Measurement_Conversion_API/__init__.py b/Package_Measurement_Conversion_API/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Package_Measurement_Conversion_API/controller/conversion_history.db b/Package_Measurement_Conversion_API/controller/conversion_history.db new file mode 100644 index 0000000..82fd855 Binary files /dev/null and b/Package_Measurement_Conversion_API/controller/conversion_history.db differ diff --git a/Package_Measurement_Conversion_API/controller/measurement_controller.py b/Package_Measurement_Conversion_API/controller/measurement_controller.py new file mode 100644 index 0000000..30c4324 --- /dev/null +++ b/Package_Measurement_Conversion_API/controller/measurement_controller.py @@ -0,0 +1,55 @@ +import cherrypy +import logging + +from Package_Measurement_Conversion_API.services.converter import Measurements +from Package_Measurement_Conversion_API.Utilities.db import MeasurementsDB + +# Initialize database manager and measurement conversion service +db_manager = MeasurementsDB("conversion_history.db") +Measure = Measurements() + +# Configure logging +logging.basicConfig(filename='Package_Measurement_Conversion_API\logging\error_log.log', + level=logging.CRITICAL, format='%(asctime)s:%(levelname)s:%(message)s') + + +class MeasurementService(object): + + @cherrypy.expose + @cherrypy.tools.json_out() + def get_data_from_db(self): + """Fetch conversion history from the database.""" + try: + table = db_manager.display_table() + return {"status": "success", "err_msg": "", "result": table} + except Exception as e: + logging.error(f"Failed to retrieve data: {str(e)}") + return {"status": "fail", "err_msg": str(e), "result": []} + + @cherrypy.expose + @cherrypy.tools.json_out() + def convert_measurements(self, input_string): + """Convert input string to numbers based on specific logic.""" + try: + if not isinstance(input_string, str): + raise ValueError("Input must be a string.") + + converted_data = Measure.convert_measurements(input_string) + if not converted_data: + raise ValueError("Conversion resulted in empty data.") + return {"status": "success", "err_msg": "", "result": converted_data} + except Exception as e: + logging.exception("Error in convert_measurements:") + return {"status": "fail", "err_msg": str(e), "result": []} + + @cherrypy.expose + @cherrypy.tools.json_out() + def conversion_results(self, input_string): + """Process converted data to compute final results and save them to the database.""" + try: + results = Measure.measurement_results(input_string) + db_manager.save_table(input_string, results) # Assuming the function name is save_conversion + return {"status": "success", "err_msg": "", "result": results} + except Exception as e: + logging.error(f"Failed to process conversion results: {str(e)}") + return {"status": "fail", "err_msg": str(e), "result": []} diff --git a/Package_Measurement_Conversion_API/readme.md b/Package_Measurement_Conversion_API/readme.md new file mode 100644 index 0000000..782b36d --- /dev/null +++ b/Package_Measurement_Conversion_API/readme.md @@ -0,0 +1,76 @@ +# Package Measurement Conversion API + +This API is designed to convert measurement input strings into a list of total values of measured inflows for each package. The input strings follow a specific encoding format, where each package consists of a number indicating the count of values measured in each measurement cycle, followed by the measured values encoded using alphabetical characters. + +## Pre-requisites + +- Python 3.x +- CherryPy +- SQLite + +## Installation + +### 1. Clone the repository: + + https://github.com/Sughiya-AlSaid/PackageMeasurementConversionAPI + + +### 2. Navigate to the project directory: + + cd Package_Measurement_Conversion_API + +### 3. Install the required dependencies: + + pip install -r requirements.txt + +## Running the Application + +### 1. Start the server application: + + python main_app.py [port_number] + +Replace `[port_number]` with the desired port number. If no port number is provided, the application will run on the default port. + +### 2. The server will start, and you should see log messages indicating the application's status. + +## API Usage +### 1. To view the converted alphabet input string into the corresponding list of numbers in JSON format. + +The API provides a GET endpoint `/convert_measurements` that accepts a query parameter `input` containing the measurement input string. + +### Example requests: + + GET /convert_measurements?input="aa" + + GET /convert_measurements?input="abbcc" + + GET /convert_measurements?input="dz_a_aazzaaa" + +### 2. To view the list of total values of the parsed string and return the result in JSON format. + +The API provides a GET endpoint `/conversion_results` that accepts a query parameter `input` containing the measurement input string. + +### Example requests: + + GET /conversion_results?input="aa" + + GET /conversion_results?input="abbcc" + + GET /conversion_results?input="dz_a_aazzaaa" +### To retrieve the stored request history, use the following endpoint: + + GET /get_data_from_db + +This endpoint will return the persisted history of all requests made to the conversion endpoint. + +## Testing + +The application follows the principles of Test-Driven Development (TDD). Unit tests are provided in the `test/` directory. To run the tests, execute the following command: + + python -m unittest Package_Measurement_Conversion_API/services/test/test_converter.py + +## Contributing +Contributing to this project is **prohibited**. + +## Acknowledgements +This project was done by **Sughiya Al Said** \ No newline at end of file diff --git a/Package_Measurement_Conversion_API/requirements.txt b/Package_Measurement_Conversion_API/requirements.txt new file mode 100644 index 0000000..2a13a41 --- /dev/null +++ b/Package_Measurement_Conversion_API/requirements.txt @@ -0,0 +1,3 @@ +CherryPy==18.6.0 +SQLAlchemy==1.4.31 +pytest==7.1.2 diff --git a/Package_Measurement_Conversion_API/services/__init__.py b/Package_Measurement_Conversion_API/services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Package_Measurement_Conversion_API/services/converter.py b/Package_Measurement_Conversion_API/services/converter.py new file mode 100644 index 0000000..7be358b --- /dev/null +++ b/Package_Measurement_Conversion_API/services/converter.py @@ -0,0 +1,68 @@ +class Measurements(object): + def __init__(self): + pass + + def convert_measurements(self, input_string): + # Initialize the results list and the current sum. + results = [] + current_sum = 0 + + # Keep track of the count for each input + input_count = 0 + + # Loop through each character in the input string. + for char in input_string: + if char == '_': + # When facing an underscore, append the current sum to results then reset it to 0. + results.append(current_sum) + current_sum = 0 + input_count = 0 + elif 'a' <= char <= 'z': + # Convert the alphabet to their number value (a=1, b=2, etc..). + input_count += 1 + current_sum += ord(char) - ord('a') + 1 + + if input_count > 0 and current_sum > 0: + # append the sum to the result list if input_count and current sum have a value + results.append(current_sum) + current_sum = 0 + input_count = 0 + + return results + + def measurement_results(self, input_str): + # Convert the input str from the url into a list of numbers then start the count + + list_of_num = self.convert_measurements(input_str) + result_input_list = [] + is_a_step = True # First character/number = step one. + step_count_remaining = 0 # Set the count as soon as the number is encountered. + curr_input_sum = 0 # continue adding the values until remaining step count != 0 + # i = 0 + for curr_num in list_of_num: + # i += 1 + if is_a_step: + if curr_num == 26: # Check if current character is Z count + step_count_remaining += curr_num + elif curr_num == 0: # Check if current Character is underscore + result_input_list.append(0) + break + else: + step_count_remaining += curr_num + is_a_step = False + elif step_count_remaining > 0: + if curr_num == 26: + curr_input_sum += curr_num + else: + curr_input_sum += curr_num + step_count_remaining -= 1 + + if step_count_remaining == 0: # append the measurement result then reset the count before exiting + result_input_list.append(curr_input_sum) + curr_input_sum = 0 + step_count_remaining = 0 + is_a_step = True + # elif step_count_remaining > (len(list_of_num) - 1) - i: + # result_input_list = [] + + return result_input_list diff --git a/Package_Measurement_Conversion_API/services/test/__init__.py b/Package_Measurement_Conversion_API/services/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Package_Measurement_Conversion_API/services/test/test_converter.py b/Package_Measurement_Conversion_API/services/test/test_converter.py new file mode 100644 index 0000000..75777e7 --- /dev/null +++ b/Package_Measurement_Conversion_API/services/test/test_converter.py @@ -0,0 +1,25 @@ +import unittest +from Package_Measurement_Conversion_API.services.converter import Measurements + + +class TestPackageConverter(unittest.TestCase): + # Testing both Valid and Invalid inputs + + def setUp(self): + self.converter = Measurements() + + def test_conversion(self): + self.assertEqual(self.converter.measurement_results("aa"), [1]) + self.assertEqual(self.converter.measurement_results("__"), [0]) + self.assertEqual(self.converter.measurement_results("a_"), [0]) + self.assertEqual(self.converter.measurement_results('abbcc'), [2, 6]) + self.assertEqual(self.converter.measurement_results('abcdabcdab'), [2, 7, 7]) + self.assertEqual(self.converter.measurement_results('abcdabcdab_'), [2, 7, 7, 0]) + self.assertEqual(self.converter.measurement_results('dz_a_aazzaaa'), [28, 53, 1]) + self.assertEqual(self.converter.measurement_results('zdaaaaaaaabaaaaaaaabaaaaaaaabbaa'), [34]) + self.assertEqual(self.converter.measurement_results('za_a_a_a_a_a_a_a_a_a_a_a_a_azaaa'), [40, 1]) + self.assertEqual(self.converter.measurement_results('zza_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_a_'), [26]) + + +if __name__ == '__main__': + unittest.main() diff --git a/conversion_history.db b/conversion_history.db new file mode 100644 index 0000000..a182f02 Binary files /dev/null and b/conversion_history.db differ diff --git a/main_app.py b/main_app.py new file mode 100644 index 0000000..edd7eb9 --- /dev/null +++ b/main_app.py @@ -0,0 +1,16 @@ +import cherrypy + +from Package_Measurement_Conversion_API.controller.measurement_controller import MeasurementService + + +if __name__ == '__main__': + config = { + '/': { + 'tools.sessions.on': True, + 'tools.response_headers.on': True, + 'tools.response_headers.headers': [('Content-Type', 'application/json')], + } + } + cherrypy.config.update({'server.socket_host': "0.0.0.0"}) + cherrypy.config.update({'server.socket_port': 8080}) + cherrypy.quickstart(MeasurementService(), '/', config)