Skip to content

Code review - #1

Open
Ihebdhouibi wants to merge 26 commits into
masterfrom
review-branch
Open

Code review#1
Ihebdhouibi wants to merge 26 commits into
masterfrom
review-branch

Conversation

@Ihebdhouibi

Copy link
Copy Markdown
Owner

This is a self-done code review to locate areas where improvements can be made

Comment thread ImagesScrapper.py
import requests
from bs4 import BeautifulSoup
import pandas as pd
import numpy as np

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused imports

Comment thread ImagesScrapper.py
from PIL import Image
import signal
import platform
import threading

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using threading.timer to provide timeout mechanism for windows

Comment thread ImagesScrapper.py Outdated
if self.os_is_windows:
# For better portability a timeout class for windows is needed
self.timer = threading.Timer(self.seconds, self._raise_timeout)
self.timer.start

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

threading.timer won't interrupt any main thread in case it's in blocking operation (i,e I/O or sleep) it waits for it to complete and raises an exception

Comment thread ImagesScrapper.py Outdated
# soup = BeautifulSoup(htmldata, 'html.parser')
# for item in soup.find_all('img'):
# print(item['src'])
number_of_images) No newline at end of file

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing commented code to provide readability

Comment thread ImagesScrapper.py Outdated
Comment thread DataBase/dataBase.py

def connect():
@contextmanager
def get_db_connection():

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

establishing DB connection manually using connect function is error-prone, instead opt for a context manager to ensure safely opening and closing connection

Comment thread DataBase/dataBase.py
@@ -1,166 +1,131 @@
import psycopg2
from configparser import ConfigParser
from contextlib import contextmanager

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

context manager in python provides a better way to allocate and release resources

Comment thread DataBase/dataBase.py Outdated

result = cursor.fetchall()
for row in result:
print(f"id {row[0]} | username : {row[1]} | password : {row[2]}")

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

avoid displaying password

Comment thread DataBase/dataBase.py
number_cam += 1

print("Number cameras = ", number_cam)
try:

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adding exception handling to database functions is mandatory to avoid any crash in case of an incorrect SQL query plus the privilege of providing meaningful logging information

Comment thread DataBase/dataBase.py
for row in fall_alerts:
print(f"ID : {row[0]} | alert time : {row[1]} | video link : {row[2]} | class : {row[3]}")

def retrieve_robbery_alerts():

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

leveraging code_reusebility is important here as a centralized function with an additional parameter to decide which table to handle is a better approach

Comment thread DataBase/dataBase.py Outdated

def storeFallAlertData(alertTime, videoLink, AlertClass):

# Establishing Connection to DB

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here it's clear there is huge similarity between store alerts functions in a way that it should be centralized into a single function

Comment thread DataBase/dataBase.py
Comment on lines 63 to 58
with get_db_connection() as (cursor, conn):
query = "insert into fall_alerts (alert_time, video_link, class) values (%s, %s, %s)"
cursor.execute(query, (alertTime, videoLink, AlertClass))
conn.commit()

def storeRobberyAlertData(alertTime, videoLink, AlertClass):

# Establishing Connection to DB
with get_db_connection() as (cursor, conn):
query = "insert into robbery_alerts (alert_time, video_link, class) values ( %s, %s, %s)"
cursor.execute(query, (alertTime, videoLink, AlertClass))
conn.commit()
try:
cursor.execute(query, (alert_time, video_link, alert_class))
conn.commit()
except Exception as e:
print(f"Error inserting alert into {alert_type}_alerts: {e}")

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

always ensure handling exception in case of an error in the given SQL query

Comment thread DataBase/dataBase.py Outdated
Comment on lines +87 to +99

No newline at end of file

def remove_camera(camera_id):

with get_db_connection() as (cursor, conn):

try:
query = "DELETE FROM cameras WHERE id = %s"
cursor.execute(query, (camera_id))
conn.commit()
print(f"Camera with ID {camera_id} removed successfully.")
except Exception as e:
print(f"Error removing camera: {e}")

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A new function to remove a camera from database can be very useful

Comment thread ImagesScrapper.py Outdated
Comment on lines -14 to -35
driver_path = '/home/iheb/chromedriver'
output_path = 'data/images/robbery_images'
number_of_images = 1000
GET_IMAGE_TIMEOUT = 2
SLEEP_BETWEEN_INTERACTIONS = 0.1
SLEEP_BEFORE_MORE = 5
IMAGE_QUALITY = 1024
search_terms = ["armed robbery",
"shop robbery",
"man wearing robber mask",
"man wearing robber mask and knife",
"shop armed looting",

"persons",
"store customers",
"faces",
"covid mask",
"person portrait",
"full body person portrait",
"person smiling"]
# search_terms = ["armed masked thief"]

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removing global variables will improve flexibility and maintainability

Comment thread ImagesScrapper.py Outdated
Comment on lines +178 to +192
with webdriver.Chrome(executable_path=driver_path) as wd:
res = fetch_image_urls(search_term, number_images, wd= wd, sleep_between_interactions=SLEEP_BETWEEN_INTERACTIONS)
with webdriver.Chrome(executable_path=config.driver_path) as wd:
res = fetch_image_urls(search_term, number_images, wd= wd, sleep_between_interactions=config.SLEEP_BETWEEN_INTERACTIONS)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

after removing global variables we can directly use config instance attributes

Comment thread DataBase/dataBase.py Outdated
Comment on lines +39 to +41
if number_cam < 4:
query = "insert into cameras (address, nom) values (%s, %s)"
cursor.execute(query, (address, nom))
conn.commit()
else:
print("Maximum number of cameras added already")
if number_cam < 4:
query = "INERT INTO cameras (address, nom) VALUES (%s, %s)"
cursor.execute(query, (address, nom))
conn.commit()
else:
print("Maximun number of cameras added already")
except Exception as e:
print(f"Error adding camera: {e}")

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ensuring the usage of parameterized querries (i,e placeholders like %s) is important to avoid SQL injection

Comment thread cloudStorage.py
Comment on lines -11 to +20
TODO: remove cloud connection string
Initialize the blob service from Azure storage connection string.

Ensures connection string is retrieved securely from env variables.
"""

connect_string = os.getenv('AZURE_STORAGE_CONNECTION_STRING')

if not connect_string:
raise EnvironmentError("AZURE_STORAGE_CONNECTION_STRING env variable not set.")

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

raising an exception here in mandatory

Comment thread cloudStorage.py Outdated
return blob_service_client

def create_azure_container():
def create_azure_container(container_name = "alerts"):

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

avoid hardcoding the container name for better flexibility

Comment thread cloudStorage.py
Comment on lines -28 to +31

container_name = "alerts"

container_client = blob_service_client.create_container(container_name)

try:
container_client = blob_service_client.create_container(container_name)
except Exception as e:
print(f"Error creating container {container_name}: {e}")

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add exception handling

Comment thread cloudStorage.py
Comment on lines -36 to +40
current_time = datetime.now()
current_day = datetime.today()
current_time = current_time.strftime("%H:%M:%S")
videoName = videoName + " " + str(current_day) + " "+ current_time + ".mp4"
blob_client = blob_service_client.get_blob_client(container="alerts", blob=videoName)
current_time = datetime.now().strftime("%H:%M:%S")
current_day = datetime.today().strftime("%Y-%m-%d")

video_name = f"{video_name} {current_day} {current_time}.mp4"
blob_client = blob_service_client.get_blob_client(container="alerts", blob=video_name)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better code here

Comment thread cloudStorage.py
Comment on lines -42 to +58
# Converting videoArray ( numpy array ) into video
# fps = 30 # 25 frames per second


# print(videoName)
output = cv2.VideoWriter(videoName, cv2.VideoWriter_fourcc(*'mp4v'), fps, (width, height), True)
for i in videoArray:
output.write(i)
output.release()

path = "./" + videoName
# print("path : ", path)
with open(path, "rb") as data :
# Uploading video to the cloud
blob_client.upload_blob(data)
# Delete file after upload

os.remove(path)
try:
with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as temp_video_file:
output = cv2.VideoWriter(temp_video_file.name, cv2.VideoWriter_fourcc(*'mp4v'), fps, (width, height), True)
for i in video_array:
output.write(i)
output.release()

with open(temp_video_file.name, "rb") as data:
# Uploading video to the cloud
blob_client.upload_blob(data)

os.remove(temp_video_file.name) # removing temporary file after upload
return blob_client.url

except Exception as e:
print(f"Error uploading video {video_name}: {e}")
return None

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using tempfile here is better than hardcoding paths to avoid cross-platform or directory not writable issues

Comment on lines -146 to +148
print('Robbery Robbery')

logging.debug(f"Robbery detected")

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of using print statements for debugging use logging

Comment on lines +59 to +66
"""
Cycle function will be automatically called within QValka main process and runs the expected Machine vision analyses
on the passed frames.


If robbery detected, The frames of the incident will be stored in the cloud And the admin will be alerted through an SMS using twilio.

"""

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is necessary to add docstrings to describe what each function does to ensure it's maintainability

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant