fix: resolve pointer exhaustion on upload rerun and TypeError float len on PDF export
This commit is contained in:
@@ -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
@@ -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] + '..'
|
||||||
|
|||||||
Reference in New Issue
Block a user