"""One-shot script to strip emojis + apply UI text changes to app.py. Run once, then delete. Idempotent if re-run (no-ops on missing patterns). """ import re, sys from pathlib import Path ROOT = Path(__file__).resolve().parent.parent APP = ROOT / "app.py" src = APP.read_text(encoding="utf-8") orig = src # ──── Phase A: Specific multi-token replacements (surgical) ───────────────── SURGICAL = [ # st.set_page_config: page_icon ('page_icon="🏠",', 'page_icon=None,'), # PAGES dict ('"manual": "🔬 Análisis manual"', '"manual": "Análisis"'), ('"search": "🔍 Buscar deals"', '"search": "Búsqueda"'), ('"inventory": "📦 Inventario"', '"inventory": "Inventario"'), ('"favorites": "⭐ Favoritos"', '"favorites": "Favoritos"'), ('"history": "📚 Histórico análisis"', '"history": "Histórico"'), ('"feed": "📡 Feed de deals"', '"feed": "Feed"'), ('"markets": "🌎 Mercados"', '"markets": "Mercados"'), # Sidebar ('st.sidebar.title("🏠 AR-House")', 'st.sidebar.title("AR-House")'), ('st.sidebar.caption("Análisis FL real estate · 100% local")', 'st.sidebar.caption("Florida real estate analysis platform")'), ('st.sidebar.metric("⭐ Favoritos"', 'st.sidebar.metric("Favoritos"'), # Page titles ('st.title("🔬 Análisis manual de deal")', 'st.title("Análisis manual de propiedad")'), ('st.title("📦 Inventario de deals scrapeados")', 'st.title("Inventario de oportunidades")'), ('st.title("⭐ Favoritos")', 'st.title("Favoritos")'), ('st.title("📚 Histórico de análisis")', 'st.title("Histórico de análisis")'), ('st.title("🔍 Buscar deals on-demand")', 'st.title("Búsqueda de propiedades")'), ('st.title("📡 Feed de deals")', 'st.title("Feed de oportunidades")'), ('st.title("🌎 Mercados monitoreados")', 'st.title("Cobertura de mercados")'), # Subheaders ('st.subheader("🤖 Veredicto final (formato no parseado)")', 'st.subheader("Veredicto final (formato no parseado)")'), ('st.subheader("💰 Análisis financiero (DealAnalyzer)")', 'st.subheader("Análisis financiero")'), ('st.subheader("✉️ Generar email (EmailComposer)")', 'st.subheader("Generar comunicación al vendedor")'), ('st.subheader("1. 🌎 Condados")', 'st.subheader("1. Condados")'), ('st.subheader("2. 🛰️ Fuentes")', 'st.subheader("2. Fuentes")'), ('st.subheader("3. 🎛️ Filtros opcionales")', 'st.subheader("3. Filtros opcionales")'), ('st.subheader("4. 🚦 Preflight + accion")', 'st.subheader("4. Verificación previa y ejecución")'), ('st.subheader("📍 Cobertura por condado")', 'st.subheader("Cobertura por condado")'), ('st.subheader("🎯 Presets disponibles (markets_database.json)")', 'st.subheader("Presets disponibles")'), ('st.subheader("🚧 Gaps de cobertura conocidos")', 'st.subheader("Limitaciones conocidas")'), # Buttons ('"◀ Anterior"', '"Anterior"'), ('"Siguiente ▶"', '"Siguiente"'), ('"✖ Limpiar banner"', '"Limpiar banner"'), ('"➕ Nuevo análisis"', '"Nuevo análisis"'), ('"💾 Guardar análisis"', '"Guardar análisis"'), ('"📄 Exportar PDF"', '"Exportar PDF"'), ('"✨ Generar email"', '"Generar email"'), ('"📂 Cargar este análisis"', '"Cargar análisis"'), ('"📋 Cargar deal de prueba (Hialeah)"', '"Cargar deal de prueba (Hialeah)"'), # VERDICT_BADGE ('"PASA": ("🟢", "#16a34a", "PASA"),', '"PASA": ("", "#047857", "PASA"),'), ('"PASA CON CONDICIONES": ("🟡", "#ca8a04", "PASA CON CONDICIONES"),', '"PASA CON CONDICIONES": ("", "#B45309", "PASA CON CONDICIONES"),'), ('"NO PASA": ("🔴", "#dc2626", "NO PASA"),', '"NO PASA": ("", "#B91C1C", "NO PASA"),'), # PROPERTY_TYPE_LABELS ('"sfr": "🏠 SFR (Single Family Residence)"', '"sfr": "SFR — Single Family Residence"'), ('"condo": "🏢 Condo"', '"condo": "Condo"'), ('"townhome": "🏘️ Townhome"', '"townhome": "Townhome"'), ('"multi_family": "🏬 Multi-family (2-4 units)"', '"multi_family": "Multi-family (2–4 units)"'), ('"land": "🌳 TERRENO / Lote vacante"', '"land": "Terreno / Vacant lot"'), ('"mobile_home": "🚐 Mobile / Manufactured home"', '"mobile_home": "Mobile / Manufactured home"'), ('"commercial": "🏛️ Commercial / Mixed-use"', '"commercial": "Commercial / Mixed-use"'), # Expanders ('with st.expander("📋 1. Inputs del deal", expanded=True):', 'with st.expander("1. Datos de la propiedad", expanded=True):'), ('with st.expander("🏘️ 1.4 Tipo de propiedad", expanded=True):', 'with st.expander("1.4 Tipo de propiedad", expanded=True):'), ('with st.expander("🔬 Análisis técnico completo (para revisión detallada)", expanded=False):', 'with st.expander("Análisis técnico completo (para revisión detallada)", expanded=False):'), # Markdown headers in technical section ('st.markdown("### 💰 Análisis financiero (DealAnalyzer)")', 'st.markdown("### Análisis financiero (DealAnalyzer)")'), ('st.markdown("### 💵 ValueEstimator (valor real vs listing)")', 'st.markdown("### ValueEstimator (valor real vs listing)")'), ('st.markdown("### 🎯 OfferStrategist (Strike/Stretch/Walk-Away + estrategia)")', 'st.markdown("### OfferStrategist (Strike/Stretch/Walk-Away + estrategia)")'), ('st.markdown("### 🤖 Veredicto coordinador (Coordinator, markdown crudo)")', 'st.markdown("### Veredicto coordinador (Coordinator, markdown crudo)")'), ('st.markdown("### 💰 Liens Inventory contra la propiedad")', 'st.markdown("### Liens inventory contra la propiedad")'), # Status messages — replace specific emoji-bearing patterns ('st.toast("Marcado como visto")', 'st.toast("Marcado como visto")'), # noop check ] for old, new in SURGICAL: if old in src: src = src.replace(old, new) # ──── Phase B: Strip emoji-prefix patterns inside f-strings/strings ───────── # These are emoji + space at start of a quoted string content. EMOJI_PREFIXES = [ '🚨🚨 ', '🚨 ', '⚠️ ', '✅ ', '❌ ', '🤖 ', '🚀 ', '💰 ', '🎯 ', '🟢 ', '🟡 ', '🔴 ', '⚪ ', '🔬 ', '💵 ', '🏛️ ', '🛡️ ', '🏢 ', '🌳 ', '🏘️ ', '🍽 ', '🌍 ', '💼 ', '💎 ', '✉️ ', '👁️ ', '💔 ', '⭐ ', '📂 ', '📊 ', '📋 ', '👆 ', '💾 ', '📄 ', '🚧 ', '✨ ', '🧠 ', '📭 ', '🌎 ', '🛰️ ', '🎛️ ', '🚦 ', '📍 ', '📡 ', '📦 ', '🔍 ', '🔗 ', '❔ ', '🔎 ', '🇺🇸 ', '🇨🇴 ', '💡 ', '🚨🚨', '🚨', '⚠️', '✅', '❌', '🤖', '🚀', '💰', '🎯', '🟢', '🟡', '🔴', '⚪', '🔬', '💵', '🏛️', '🛡️', '🏢', '🌳', '🏘️', '🍽', '🌍', '💼', '💎', '✉️', '👁️', '💔', '⭐', '📂', '📊', '📋', '👆', '💾', '📄', '🚧', '✨', '🧠', '📭', '🌎', '🛰️', '🎛️', '🚦', '📍', '📡', '📦', '🔍', '🔗', '❔', '🔎', '🇺🇸', '🇨🇴', '💡', ] for em in EMOJI_PREFIXES: src = src.replace(em, '') # ──── Phase C: Write back if changed ──────────────────────────────────────── if src != orig: APP.write_text(src, encoding="utf-8") print(f"app.py updated ({len(orig) - len(src)} chars removed)") else: print("No changes")