fix: resolve pointer exhaustion on upload rerun and TypeError float len on PDF export

This commit is contained in:
Silas Brito
2026-07-13 20:12:56 -03:00
parent ecdee26142
commit 17b849b89a
2 changed files with 40 additions and 22 deletions
+24 -18
View File
@@ -262,29 +262,35 @@ uploaded_file = st.sidebar.file_uploader(
if uploaded_file is not None: if uploaded_file is not None:
try: try:
# Read content and compute hash for deduplication logic # getvalue() reads the whole stream without pointer exhaustion across script reruns
file_bytes = uploaded_file.read() file_bytes = uploaded_file.getvalue()
file_hash = compute_hash(file_bytes) file_hash = compute_hash(file_bytes)
# Check if already processed in database # Only process if this file hash was not just processed in this session
is_processed = db.is_file_processed(file_hash) if st.session_state.get('last_processed_file') != file_hash:
# Check historical database logs
# Parse CSV is_processed = db.is_file_processed(file_hash)
df_parsed = parse_nbu_csv(file_bytes)
if not df_parsed.empty:
# Perform SQLite UPSERT operation for each parsed job
db.save_jobs(df_parsed)
if not is_processed: # Parse CSV
df_parsed = parse_nbu_csv(file_bytes)
if not df_parsed.empty:
# Perform SQLite UPSERT
db.save_jobs(df_parsed)
# Mark processed in DB and session state
db.mark_file_processed(file_hash, uploaded_file.name) db.mark_file_processed(file_hash, uploaded_file.name)
st.toast(f"Relatório '{uploaded_file.name}' importado e sincronizado no banco!", icon="") st.session_state['last_processed_file'] = file_hash
if not is_processed:
st.toast(f"Relatório '{uploaded_file.name}' importado e sincronizado no banco!", icon="")
else:
st.toast(f"Dados do relatório '{uploaded_file.name}' atualizados!", icon="🔄")
time.sleep(0.6)
st.rerun()
else: else:
st.info(f"O relatório '{uploaded_file.name}' já foi importado anteriormente. Os dados foram atualizados no banco.") st.error("O arquivo fornecido está vazio ou mal formatado.")
st.rerun()
else:
st.error("O arquivo fornecido está vazio ou mal formatado.")
except Exception as e: except Exception as e:
st.error(f"Erro ao processar arquivo: {str(e)}") st.error(f"Erro ao processar arquivo: {str(e)}")
+16 -4
View File
@@ -2,6 +2,18 @@ from fpdf import FPDF
import datetime import datetime
import hashlib import hashlib
def clean_str(val, default="N/A"):
"""
Safely casts database records to strings, checking for None and float NaN.
"""
if val is None:
return default
# check if float NaN
if isinstance(val, float) and val != val:
return default
s = str(val).strip()
return s if s else default
class NetBackupMitigationPDF(FPDF): class NetBackupMitigationPDF(FPDF):
""" """
Sleek, brand-aligned A4 layout representing the Veritas dark tech design system. Sleek, brand-aligned A4 layout representing the Veritas dark tech design system.
@@ -151,12 +163,12 @@ def generate_mitigation_pdf(jobs_list, filter_name="Consolidated"):
fill_row = False fill_row = False
for j in failures_list: for j in failures_list:
jid = j['job_id'] jid = j['job_id']
client = j['client'] or 'N/A' client = clean_str(j['client'])
policy = j['policy'] or 'N/A' policy = clean_str(j['policy'])
code = j['exit_code'] code = j['exit_code']
reex = 'Reexecutado' if j['is_rerun_success'] == 1 else 'Pendente' reex = 'Reexecutado' if j['is_rerun_success'] == 1 else 'Pendente'
status = j.get('status', 'Pendente') status = clean_str(j.get('status'), 'Pendente')
action = j.get('action_taken', '') or 'Nenhuma nota registrada.' action = clean_str(j.get('action_taken'), 'Nenhuma nota registrada.')
# String safety trims # String safety trims
if len(client) > 20: client = client[:18] + '..' if len(client) > 20: client = client[:18] + '..'