--- name: split_vevents_to_vcalendars kind: function lang: py domain: infra version: "1.0.0" purity: pure signature: "def split_vevents_to_vcalendars(ics_text: str, prodid: str = '-//xandikos-migracion//google-export//EN') -> list" description: "Divide un .ics (un VCALENDAR con N VEVENT) en N VCALENDARs independientes, cada uno con un unico VEVENT, header VERSION/PRODID/CALSCALE y las VTIMEZONE del original. Pura, solo stdlib (re). Util para importar a CalDAV un .ics exportado de Google Calendar que mete todos los eventos en un solo VCALENDAR: cada salida se sube como recurso .ics independiente. Normaliza saltos de linea a CRLF (RFC 5545)." tags: [dav, caldav, ical, ics, vevent, vcalendar, calendar, infra, split] uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "" imports: [re] params: - name: ics_text desc: "contenido completo del .ics: un VCALENDAR con uno o varios VEVENT. Tolera LF o CRLF." - name: prodid desc: "valor del campo PRODID del header de cada VCALENDAR de salida. Default identifica la migracion a Xandikos." output: "list[str]. Cada elemento es un VCALENDAR completo y autonomo ('BEGIN:VCALENDAR'..'END:VCALENDAR' terminado en CRLF) con header VERSION:2.0 / PRODID / CALSCALE:GREGORIAN, las VTIMEZONE del original (si las habia, replicadas en cada salida) y un unico VEVENT. Lista vacia si no hay ningun VEVENT." tested: true tests: - "test_dos_vevents_devuelve_dos_vcalendars" - "test_cada_salida_tiene_un_solo_vevent" - "test_header_vcalendar_correcto" - "test_vtimezone_se_replica_en_cada_salida" - "test_salida_termina_en_crlf" - "test_input_vacio_devuelve_lista_vacia" test_file_path: "python/functions/infra/split_vevents_to_vcalendars_test.py" file_path: "python/functions/infra/split_vevents_to_vcalendars.py" --- ## Ejemplo ```python import sys sys.path.insert(0, "python/functions") from infra.split_vevents_to_vcalendars import split_vevents_to_vcalendars ics = ( "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Google//EN\r\n" "BEGIN:VEVENT\r\nUID:a@x\r\nSUMMARY:Reunion\r\nEND:VEVENT\r\n" "BEGIN:VEVENT\r\nUID:b@x\r\nSUMMARY:Comida\r\nEND:VEVENT\r\n" "END:VCALENDAR\r\n" ) cals = split_vevents_to_vcalendars(ics) print(len(cals)) # 2 print(cals[0].count("BEGIN:VEVENT")) # 1 (un evento por VCALENDAR) ``` ## Cuando usarla Cuando exportas tu calendario de Google a un unico `.ics` (un VCALENDAR con todos los eventos dentro) y necesitas subir cada evento como recurso CalDAV separado a Xandikos. Es el primer paso del pipeline `import_ics_to_caldav`: split → extraer UID por evento → `caldav_put_event`. Cada salida es un `.ics` valido y autonomo que un cliente de calendario puede consumir por si solo. ## Gotchas Funcion pura. Replica TODAS las VTIMEZONE del VCALENDAR original en cada salida (conservador: garantiza que cualquier TZID referenciado por el VEVENT este definido, aunque algun evento no use ninguna). No deduplica ni filtra timezones por evento. No valida que el VEVENT este completo ni reescribe DTSTART /DTEND. Si el .ics no contiene VEVENT (p.ej. solo VTODO o VJOURNAL) devuelve lista vacia.