From 3c88b40a5696e4892e0f4ac8ab37dc095be05d66 Mon Sep 17 00:00:00 2001 From: Grant Ellsworth Date: Mon, 23 Feb 2026 18:48:31 -0700 Subject: [PATCH 1/6] advanced repairs --- custom_components/pdf_scrape/__init__.py | 15 +------ custom_components/pdf_scrape/config_flow.py | 20 ++++++++-- custom_components/pdf_scrape/coordinator.py | 14 ++++--- custom_components/pdf_scrape/repairs.py | 40 ++++++++++--------- .../pdf_scrape/translations/en.json | 12 ------ 5 files changed, 49 insertions(+), 52 deletions(-) diff --git a/custom_components/pdf_scrape/__init__.py b/custom_components/pdf_scrape/__init__.py index a106d6e..8147e85 100644 --- a/custom_components/pdf_scrape/__init__.py +++ b/custom_components/pdf_scrape/__init__.py @@ -47,6 +47,7 @@ async_raise_error, ) from .pdf import ( + FileError, HTTPError, PDFParseError, PDFScrapeHTTP, @@ -192,15 +193,11 @@ async def async_setup_entry( await coordinator.async_config_entry_first_refresh() - config_entry.async_on_unload( - config_entry.add_update_listener(_async_update_listener) - ) - config_entry.runtime_data = coordinator await hass.config_entries.async_forward_entry_setups(config_entry, _PLATFORMS) - except (HTTPError, TimeoutError, PDFParseError) as ex: + except (HTTPError, TimeoutError, PDFParseError, FileError) as ex: async_raise_error( hass=hass, error_key=ErrorTypes.PDF_ERROR, @@ -234,14 +231,6 @@ async def async_migrate_entry( return True -async def _async_update_listener( - hass: HomeAssistant, config_entry: PDFScrapeConfigEntry -): - """Handle config options update.""" - # Reload the integration when the options change. - await hass.config_entries.async_reload(config_entry.entry_id) - - async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Unload a config entry.""" return await hass.config_entries.async_unload_platforms(entry, _PLATFORMS) diff --git a/custom_components/pdf_scrape/config_flow.py b/custom_components/pdf_scrape/config_flow.py index 1cd257f..e792006 100644 --- a/custom_components/pdf_scrape/config_flow.py +++ b/custom_components/pdf_scrape/config_flow.py @@ -199,7 +199,13 @@ async def async_step_http( "minutes": minutes, "seconds": seconds, } - flow_schema = self.add_suggested_values_to_schema(flow_schema, data) + flow_schema = self.add_suggested_values_to_schema( + flow_schema, + { + **self._get_reconfigure_entry().data, + CONF_NAME: self._get_reconfigure_entry().title, + }, + ) else: hours, remainder = divmod(CONF_DEFAULT_SCAN_INTERVAL.total_seconds(), 3600) minutes, seconds = divmod(remainder, 60) @@ -279,7 +285,11 @@ async def async_step_upload( ) if self.source == SOURCE_RECONFIGURE: flow_schema = self.add_suggested_values_to_schema( - flow_schema, self._get_reconfigure_entry().data + flow_schema, + { + **self._get_reconfigure_entry().data, + CONF_NAME: self._get_reconfigure_entry().title, + }, ) return self.async_show_form( data_schema=flow_schema, @@ -337,7 +347,11 @@ async def async_step_local( ) if self.source == SOURCE_RECONFIGURE: flow_schema = self.add_suggested_values_to_schema( - flow_schema, self._get_reconfigure_entry().data + flow_schema, + { + **self._get_reconfigure_entry().data, + CONF_NAME: self._get_reconfigure_entry().title, + }, ) elif user_input is not None: flow_schema = self.add_suggested_values_to_schema(flow_schema, user_input) diff --git a/custom_components/pdf_scrape/coordinator.py b/custom_components/pdf_scrape/coordinator.py index 5ca023c..a9039cf 100644 --- a/custom_components/pdf_scrape/coordinator.py +++ b/custom_components/pdf_scrape/coordinator.py @@ -200,7 +200,7 @@ def async_raise_error( hass: HomeAssistant, error_key: str, config_entry: PDFScrapeConfigEntry, - exception: Exception, + exception: Exception | None = None, translation_placeholders: dict[str, Any] | None = None, config_subentry: ConfigSubentry | None = None, ) -> None: @@ -211,11 +211,13 @@ def async_raise_error( translation_placeholders["conf"] = ( config_entry.title if config_subentry is None else config_subentry.title ) - msg = ( - str(exception) - if not isinstance(exception, PDFParseError) - else "Unable to parse pdfS" - ) + msg: str = "" + if exception is not None: + msg = ( + str(exception) + if not isinstance(exception, PDFParseError) + else "Unable to parse pdf" + ) translation_placeholders["msg"] = msg data: dict[str, Any] = { "entry_id": config_entry.entry_id, diff --git a/custom_components/pdf_scrape/repairs.py b/custom_components/pdf_scrape/repairs.py index 1a83d73..d5abaa4 100644 --- a/custom_components/pdf_scrape/repairs.py +++ b/custom_components/pdf_scrape/repairs.py @@ -11,7 +11,8 @@ ConfigFlowContext, ConfigFlowResult, FlowType, - # SubentryFlowContext, + SubentryFlowContext, + SubentryFlowResult, ) from homeassistant.core import HomeAssistant @@ -40,7 +41,7 @@ async def async_step_confirm( description_placeholders={"msg": self.data["msg"]}, ) - async def _async_get_next_flow(self) -> ConfigFlowResult: + async def _async_get_next_flow(self) -> data_entry_flow.FlowResult: raise NotImplementedError("Must be implemented by subclasses.") @@ -48,32 +49,35 @@ class PDFRepairFlow(PDFScrapeRepairFlow): """Repair for PDF errors.""" async def _async_get_next_flow(self) -> ConfigFlowResult: - next_flow: ConfigFlowResult = self.hass.config_entries.flow.async_init( + next_flow: ConfigFlowResult = await self.hass.config_entries.flow.async_init( DOMAIN, context=ConfigFlowContext( entry_id=self.data["entry_id"], source=SOURCE_RECONFIGURE ), ) - result: ConfigFlowResult = self.async_abort(reason="next_flow") - result["next_flow"] = (FlowType.CONFIG_FLOW, next_flow["flow_id"]) - return result + return self.async_create_entry( + data={}, next_flow=(FlowType.CONFIG_FLOW, next_flow["flow_id"]) + ) class TargetRepairFlow(PDFScrapeRepairFlow): """Repair for Target Errors.""" - async def _async_get_next_flow(self) -> ConfigFlowResult: - return self.async_abort(reason="manual_fix") - - # async def _async_get_next_flow(self) -> ConfigFlowResult: - # return await self.hass.config_entries.subentries.async_init( - # (self.data["entry_id"], "target"), - # context=SubentryFlowContext( - # entry_id=self.data["entry_id"], - # subentry_id=self.data["subentry_id"], - # source=SOURCE_RECONFIGURE, - # ), - # ) + async def _async_get_next_flow(self) -> SubentryFlowResult: + next_flow: SubentryFlowResult = ( + await self.hass.config_entries.subentries.async_init( + (self.data["entry_id"], "target"), + context=SubentryFlowContext( + entry_id=self.data["entry_id"], + subentry_id=self.data["subentry_id"], + source=SOURCE_RECONFIGURE, + ), + ) + ) + return self.async_create_entry( + data={}, + next_flow=(FlowType.CONFIG_SUBENTRIES_FLOW, next_flow["flow_id"]), + ) async def async_create_fix_flow( diff --git a/custom_components/pdf_scrape/translations/en.json b/custom_components/pdf_scrape/translations/en.json index 6d2ffb5..c114bb1 100644 --- a/custom_components/pdf_scrape/translations/en.json +++ b/custom_components/pdf_scrape/translations/en.json @@ -266,9 +266,6 @@ "title": "Page(s) Out of Range ({conf})", "description": "{msg} \n \nContinue?" } - }, - "abort": { - "manual_fix": "This issue requires a manual fix. Please open the subentry configuration, and change the settings to fix this issue." } } }, @@ -280,9 +277,6 @@ "title": "Regular Expression Error ({conf})", "description": "{msg} \n \nContinue?" } - }, - "abort": { - "manual_fix": "This issue requires a manual fix. Please open the subentry configuration, and change the settings to fix this issue." } } }, @@ -294,9 +288,6 @@ "title": "No Matches Found ({conf})", "description": "{msg} \n \nContinue?" } - }, - "abort": { - "manual_fix": "This issue requires a manual fix. Please open the subentry configuration, and change the settings to fix this issue." } } }, @@ -308,9 +299,6 @@ "title": "Template Error ({conf})", "description": "{msg} \n \nContinue?" } - }, - "abort": { - "manual_fix": "This issue requires a manual fix. Please open the subentry configuration, and change the settings to fix this issue." } } } From 166180e9f996d33fe32bd68cc10985128316e0d9 Mon Sep 17 00:00:00 2001 From: Grant Ellsworth Date: Mon, 18 May 2026 18:52:06 -0400 Subject: [PATCH 2/6] Switch to pymupdf --- README.md | 4 +- custom_components/pdf_scrape/__init__.py | 145 +++-- .../pdf_scrape/brand/dark_icon.png | Bin 0 -> 8791 bytes .../pdf_scrape/brand/dark_icon@2x.png | Bin 0 -> 18686 bytes .../pdf_scrape/brand/dark_logo.png | Bin 0 -> 36264 bytes .../pdf_scrape/brand/dark_logo@2x.png | Bin 0 -> 83896 bytes custom_components/pdf_scrape/brand/icon.png | Bin 0 -> 8966 bytes .../pdf_scrape/brand/icon@2x.png | Bin 0 -> 18954 bytes custom_components/pdf_scrape/brand/logo.png | Bin 0 -> 38151 bytes .../pdf_scrape/brand/logo@2x.png | Bin 0 -> 88254 bytes custom_components/pdf_scrape/config_flow.py | 544 ++++++++++------ custom_components/pdf_scrape/const.py | 10 +- custom_components/pdf_scrape/coordinator.py | 20 +- custom_components/pdf_scrape/manifest.json | 4 +- custom_components/pdf_scrape/pdf.py | 584 ++++++++++++------ custom_components/pdf_scrape/repairs.py | 21 +- custom_components/pdf_scrape/sensor.py | 57 +- .../pdf_scrape/translations/en.json | 57 +- hacs.json | 2 +- logo.svg | 14 - 20 files changed, 974 insertions(+), 488 deletions(-) create mode 100644 custom_components/pdf_scrape/brand/dark_icon.png create mode 100644 custom_components/pdf_scrape/brand/dark_icon@2x.png create mode 100644 custom_components/pdf_scrape/brand/dark_logo.png create mode 100644 custom_components/pdf_scrape/brand/dark_logo@2x.png create mode 100644 custom_components/pdf_scrape/brand/icon.png create mode 100644 custom_components/pdf_scrape/brand/icon@2x.png create mode 100644 custom_components/pdf_scrape/brand/logo.png create mode 100644 custom_components/pdf_scrape/brand/logo@2x.png delete mode 100644 logo.svg diff --git a/README.md b/README.md index 6cff50d..17be842 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ![PDFScrape Logo](logo.svg) Integration +# PDFScrape Integration [![hacs_badge](https://img.shields.io/badge/HACS-Custom-orange.svg?style=flat-square&logo=homeassistantcommunitystore)](https://hacs.xyz/) @@ -19,8 +19,6 @@ Configuration via Homeassistant UI. The recommended way to install this is via HACS: - - [![Open your Home Assistant instance and open a repository inside the Home Assistant Community Store.](https://my.home-assistant.io/badges/hacs_repository.svg)](https://my.home-assistant.io/redirect/hacs_repository/?category=custom_respository&owner=iluvdata&repository=pdf_scrape) #### Semi-manual install diff --git a/custom_components/pdf_scrape/__init__.py b/custom_components/pdf_scrape/__init__.py index 8147e85..982e32c 100644 --- a/custom_components/pdf_scrape/__init__.py +++ b/custom_components/pdf_scrape/__init__.py @@ -1,13 +1,15 @@ """PDF Scrape Integration.""" +from asyncio import TaskGroup +from collections.abc import Awaitable, Callable +from functools import partial import logging +from pathlib import Path from typing import Any import voluptuous as vol from homeassistant.components.file_upload import process_uploaded_file - -# import aiohttp from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( ATTR_CONFIG_ENTRY_ID, @@ -26,14 +28,15 @@ import homeassistant.helpers.config_validation as cv import homeassistant.helpers.device_registry as dr from homeassistant.helpers.selector import FileSelector, FileSelectorConfig -from homeassistant.helpers.storage import Store +from homeassistant.helpers.storage import STORAGE_DIR, Store from homeassistant.helpers.typing import ConfigType from .const import ( CONF_FILE, - CONF_MD5_CHECKSUM, CONF_MODIFIED, CONF_MODIFIED_SOURCE, + CONF_SHA256_CHECKSUM, + DOCUMENT_SUBENTRY, DOMAIN, ConfType, ErrorTypes, @@ -41,19 +44,19 @@ from .coordinator import ( PDFScrapeConfigEntry, PDFScrapeCoordinator, + PDFScrapeFileCoordinator, PDFScrapeHTTPCoordinator, - PDFScrapeLocalCoordinator, PDFScrapeUploadCoordinator, async_raise_error, ) from .pdf import ( + PDF, FileError, HTTPError, PDFParseError, + PDFScrapeFile, PDFScrapeHTTP, - PDFScrapeLocal, PDFScrapeUpload, - StoredFile, get_store, ) @@ -64,6 +67,13 @@ CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN) +async def async_run_in_loop[*_Ts, _T]( + hass: HomeAssistant, target: Callable[[*_Ts], _T], *args: *_Ts +) -> Awaitable[_T]: + """Run a function in the executor.""" + return await hass.async_add_executor_job(target, *args) + + async def async_setup(hass: HomeAssistant, config_type: ConfigType) -> bool: """Setup service.""" @@ -94,11 +104,11 @@ async def upload_pdf(call: ServiceCall) -> ServiceResponse: ) # Reload the config entry to pick up the new file hass.config_entries.async_schedule_reload(config_entry.entry_id) - if pdf.modified is not None: + if pdf.pdf.modified is not None: return { - CONF_MODIFIED: pdf.modified.isoformat(), - CONF_MODIFIED_SOURCE: pdf.modified_source, - CONF_MD5_CHECKSUM: pdf.md5_checksum, + CONF_MODIFIED: pdf.pdf.modified.isoformat(), + CONF_MODIFIED_SOURCE: pdf.pdf.modified_source, + CONF_SHA256_CHECKSUM: pdf.pdf.md5_checksum, } error = "Unable to parse uploaded PDF" except PDFParseError as ex: @@ -144,6 +154,41 @@ def _one_of(data: dict[str, Any]) -> dict[str, Any]: SCHEMA, SupportsResponse.OPTIONAL, ) + + # Clean up orphaned files if present + # List of valid entries (and temp_ids) + config_entry_ids: list[str] = [ + entry.entry_id + if entry.data.get("temp_storage_id") is None + else entry.data.get("temp_storage_id") + for entry in hass.config_entries.async_entries(DOMAIN) + ] + path: Path = Path(hass.config.path(STORAGE_DIR)) + async with TaskGroup() as tg: + for file in await hass.async_add_executor_job(path.iterdir): + if file.is_file() and file.name.startswith(f"{DOMAIN}_"): + entry_or_flow_id: str = file.name.removeprefix(f"{DOMAIN}_") + if entry_or_flow_id not in config_entry_ids and ( + store := get_store(hass, entry_or_flow_id) + ): + _LOGGER.warning( + "Removing orphaned store: %s. Note: This is not an error but indicates that the store is not associated with any config entry", + store.path, + ) + tg.create_task(store.async_remove()) + path = path.joinpath(DOMAIN) + if await hass.async_add_executor_job(path.exists): + for file in await hass.async_add_executor_job(path.iterdir): + if ( + file.suffix in [".pdf", ".webp"] + and file.stem not in config_entry_ids + ): + _LOGGER.warning( + "Removing orphaned file: %s. Note: This is not an error but indicates that the file is not associated with any config entry", + file, + ) + tg.create_task(async_run_in_loop(hass, file.unlink)) + return True @@ -151,6 +196,8 @@ async def async_setup_entry( hass: HomeAssistant, config_entry: PDFScrapeConfigEntry ) -> bool: """Set up the config entry.""" + if not config_entry.get_subentries_of_type(DOCUMENT_SUBENTRY.subentry_type): + hass.config_entries.async_add_subentry(config_entry, DOCUMENT_SUBENTRY) try: coordinator: PDFScrapeCoordinator match config_entry.data[CONF_TYPE]: @@ -166,14 +213,39 @@ async def async_setup_entry( # Rename the storage file that was created by the config flow (one time only) if temp_store := get_store(hass, temp_key): if data := await temp_store.async_load(): - new_store: Store[StoredFile] = get_store( + new_store: Store[PDF] = get_store( hass, config_entry.entry_id ) await new_store.async_save(data) await temp_store.async_remove() hass.config_entries.async_update_entry( - config_entry, data={"type": "upload"} + config_entry, data={"type": ConfType.UPLOAD} ) + # rename the pdf file. + path: Path = Path(hass.config.path(STORAGE_DIR), DOMAIN) + async with TaskGroup() as tg: + tg.create_task( + async_run_in_loop( + hass, + partial( + path.joinpath(f"{temp_key}.pdf").rename, + path.joinpath( + f"{config_entry.entry_id}.pdf" + ), + ), + ) + ) + tg.create_task( + async_run_in_loop( + hass, + partial( + path.joinpath(f"{temp_key}.webp").rename, + path.joinpath( + f"{config_entry.entry_id}.webp" + ), + ), + ) + ) else: raise ConfigEntryError("Temp store empty") else: @@ -184,12 +256,12 @@ async def async_setup_entry( ) coordinator = PDFScrapeUploadCoordinator(hass, config_entry, pdfupload) case ConfType.LOCAL: - pdflocal: PDFScrapeLocal = await PDFScrapeLocal.pdfscrape( + pdflocal: PDFScrapeFile = await PDFScrapeFile.pdfscrape( hass, config_entry.data[CONF_FILE], config_entry_id=config_entry.entry_id, ) - coordinator = PDFScrapeLocalCoordinator(hass, config_entry, pdflocal) + coordinator = PDFScrapeFileCoordinator(hass, config_entry, pdflocal) await coordinator.async_config_entry_first_refresh() @@ -205,30 +277,21 @@ async def async_setup_entry( exception=ex, ) + config_entry.async_on_unload(config_entry.add_update_listener(update_listener)) + return True -async def async_migrate_entry( - hass: HomeAssistant, config_entry: PDFScrapeConfigEntry +async def async_remove_config_entry_device( + hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.DeviceEntry ) -> bool: - """Check for config migration.""" - - if config_entry.version == 1 and config_entry.minor_version == 1: - new_data: dict[str, Any] = {**config_entry.data} - # Move data to store and remove from config_entry data - data: StoredFile = {} - for k, v in new_data.items(): - if k in [CONF_MODIFIED, CONF_MODIFIED_SOURCE, CONF_MD5_CHECKSUM]: - data[k] = v - del new_data[k] - store: Store[StoredFile] = get_store(hass, config_entry.entry_id) - await store.async_save(data) - - hass.config_entries.async_update_entry( - config_entry, data=new_data, version=1, minor_version=2 - ) + """Handle pre-device delete checks.""" + # TODO: Tesseract device: Also delete config_entry - return True + +async def update_listener(hass: HomeAssistant, config_entry: ConfigEntry): + """Process update (when subentries are added).""" + hass.config_entries.async_schedule_reload(config_entry.entry_id) async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: @@ -239,5 +302,15 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None: """Handle removal of an entry.""" # Delete the store - if store := get_store(hass, entry.entry_id): - await store.async_remove() + await async_cleanup(hass, entry.entry_id) + + +async def async_cleanup(hass: HomeAssistant, entry_or_flow_id: str) -> None: + """Handle cleanup after removed entry and config flow error.""" + # Remove storage files + path: Path = Path(hass.config.path(".storage", DOMAIN)) + async with TaskGroup() as tg: + for file in async_run_in_loop(hass, path.glob(f"{entry_or_flow_id}.*")): + tg.create_task(async_run_in_loop(hass, file.unlink)) + if store := get_store(hass, entry_or_flow_id): + tg.create_task(store.async_remove()) diff --git a/custom_components/pdf_scrape/brand/dark_icon.png b/custom_components/pdf_scrape/brand/dark_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..97ecbd887fdbc0c1c5afa525af3123f4d9ef5a3d GIT binary patch literal 8791 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 PC_r6VTdCraRq+1;IQVER literal 0 HcmV?d00001 diff --git a/custom_components/pdf_scrape/brand/dark_icon@2x.png b/custom_components/pdf_scrape/brand/dark_icon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..19d90f140127b0b41d97a7cc18b3e4f18b1f798e GIT binary patch literal 18686 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 I_e@{^U&<1~Hvj+t literal 0 HcmV?d00001 diff --git a/custom_components/pdf_scrape/brand/dark_logo.png b/custom_components/pdf_scrape/brand/dark_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..add703cfc56ee35fb847809a82766df6f325bc68 GIT binary patch literal 36264 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 N1fH&bF6*2UngHoC&Jq9s literal 0 HcmV?d00001 diff --git a/custom_components/pdf_scrape/brand/dark_logo@2x.png b/custom_components/pdf_scrape/brand/dark_logo@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e49c3abfd1ebdb779131ecbde1e2213e8790cf9e GIT binary patch literal 83896 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%0DJQY@!Pcxk0Xf16F9VzC#WI<(InR!ug-f!5 zRtu3medmwY4o*z#QKN2;4U=4zll~wJhm#8R^Sc_hvs-!vzjj~4oFIYShMmlTQr^ct z0;}ikJAGpX^wPSO3^g3p(Oc2eFsHESK}cT7`PLOD1qQXsl8C7>)eF<|CG~RZLXV5U zkgnGIJIC>v)N>7g*qBi_%8gJYg=12KFKwaXmVuE9J~8@@*7bLNt{aY4Ei-!Xsf_bym+Dx?3MO?cke9z5*E*U+o45h;JyZ-=fk9i%zrS8Pug~KMr71Usw2Cv6d|XM zOf_O3XQB1r*%l%Oih2>7Dj#nDfnaF#Id@CpxOyp8Qf=Rl)1E*cM#oqxOZfC_rwyHC zAr<~YS(V4@2f~m?_>vgD%i4OXI_y~=4PypTp1pk_>??JHP2Gr_^Ae(ywHcf*T)s4F zIV3|F)K|4-BU}IYGEbwl)unc$ib40hXQ-LaIIeixjc@#>#yL8#foi+*I+tBjgz#CS z)_m}0)t0jtb-$RsJBctP(ts??IEv*ojDGRv_i-7t6XCkl_pGlJ2r4etxW~Tih2W6(ctV{Z1 zjqNdRKQ1<%Zfl(OC$8q`rk9*#X!kM%3@y`51&OShS+S|Xcm6cKZ!oX;9-zihgC4Mi z5cS(VYfgx(FPrC^K?$QsJNCUbv5{mJ|9=3*$YT zpysoh;93%|jjg2Ax^evi3|K^u2cAEh4iNF<@tFfA2aciE%$y zZViIh_GRzw@pJFGv&lDQi#Ec&;Zi6Nh`>}=d7eDfrd@j+ZC7vV5L`2VdltFL2+e|G z+@8F)y5p>mD`yw}vL5M!{+l1zoFET6r7(=l=#qqLQj34=Ov+Ysk_EO&cE3M5Yf;2ht5=Il{p9ZS6Ew(u7;P{|?rXl%eNGNL!jnVEJRkD#81it( z&SL9n?6wL`@-Jf>cN-XWYDw4!NYeds-lQ+qnj3?oq04V0V5qbE4iwGXQR=2L5wtIw znPlb`WC6Bannlv_d$-p-Kgnfyp;wS7HKW@D6#_}_Hq6-c8`nfb`I)L|O~TryoIL72 zo_96xOhXyrtfYX*m~n#}dZas%N?4o4ZymVnd(FM3nysJ#8=wyt`r;qaq7D}ljz5|) zVH-o>$VRk@+bSkjQH>-OGM5`yhH@-0PKj|(GJM10hd@;9GI|)|yKsB>JT{)^(?1Kj zs(rgIIV!DyUYu-nsxRfY*+OpW2nl>--P?w|T@Q{bN!7q5o zE!m}`Y^6byz)1NW#;{=o$wh)$C0U4>X0^+3`fx_xtd|%M-dzE}i$U;?|7^ZrN+)dL z^ztMY2C^({mSLeuF{61IL%Nn7m?uttp3y+n*Zn&vS-E^X*SoKty0Cb%>GI7Dg~1H| z_guMW^2`S%dud&mS+!o`o55EtSoiBSCt(6qR^RuqZDgIOZBv))Kg|I5rk_EKo2FzP zX^vRDd~+;zSmbs2Y6y#(7@Q)Zx>e{IP#^lPVkdIZ@teck?E?o>K078N25m>~GLEw> z$#t~`J?Yqnw)Nr@ih)gqx|uKBOzwme!ryDVyk0{adI7_lcOqr4?Dfgi z-m&AR`r|cz2O?38WoAK+0lt}xBIi_mdaamoVN_89>gVK;?G%BR`&17vm7Tz8?K zk6}v%mZ3chF_+eE4GZyVL(8Et5&P*2LVb9{(KD2K*hSA!_WEjA@6xv0=%a~ID8d?d z%7BhS+J?Ct3r6}_T|#I^&n4{xF60xs&Ipl7r9H;icOCgD@+RLKsMy1xMb}kJHxjRk z0$WBUZs^u`x7}jLaMK#7uGj-fsAW9fK3L)_V3MU--x-@9T&UAPWS|;JoNbiM3>2AI zu{&okikPHtjDF@gVJ}A1Wk_eDh6Z)W)1kF_5ZtSL@EYkO9@V!4^jG2kkp zUfWLDQN#vahp813IJ`PMlXA;9F&SA|^-0^zH>uBY6FYd+-lQePUXC&)@p^VF(otS2V=I&f}1C`>)jQ;~Qr?L?n;mc_NpzypAr+LS=(eH?L zDG6>(Hq?#q_Ab5Bes=+dINzPPJ-*SZ1vtaHRqwWysExP}6dvQ~>h93e5J+<2?ye$E z^42HXeOK=6^#%=Z2yq?zr`!ab{OAPn-#|W#YkTC0Qv(&?J5RNw6)<<8FU_X7_YxPc zdfVdGs^8wsEb#0*k3PCe@!I*k?N;`wl!eexapwnBcOckRoqTy-=5OA$Brka5A1KPV z%z7mY(R`r{0QTe|@x|`e6mh#~E|!`G(+@ozOChDtaX)aR7_GfLx40%4i(vif_%AkV zMU@}y4maBKnv)3o#+??N#-MkcXZ7UCXk~lB5pA4M(@*P9XAW2ovQ$7b#i|E3=j2T)8BxhZ+EpJM3UeLE4 z2#6e9C{NG*mtllUL>D#fC|0^yf$F|XmKuSGc$-0=bC_N{VUs0PPo*7$ zv0of6@LbvH1*Mn+;~{$PQv8D&B|XC8gVbD~-_hz!0Y08LZZ;y;E0Vw7ppE%Hc~!H{ z>H2PpOz!}*5Nt-&5wJiq=NTr^?+rHAYO_xcH()Y;c>@oMvZqGAZX$^fc^D^kvNDvQ z{iD`SCMNQ3d@16O^=kt$c&JS2pR6_Bb?MrAPe$6Glv`<~~mbfjklQ$w?rx zXvVEfLW1x~19FZ*1uj%P-I0Z2vH@weg4i6$HY@kfm?zVEh@z z#zd+N237^>nEFLsRi0a+NAQKhb`qMfLg{jd)xfjdN{#W4cp1jbn%CZ$M}$UlFs6wJ z%_^wRNj}Hc!E^?NtRetunnPO)>X|QCzY#}B=-~lVoomyJ1qteqBHlKih4vX7lR|BN z;URxluiHbT^&6EXw^qxj3;Xeqc7o$Q3qLj!o^vqN)iRYU&R6bm4;`;IcR)23JCB)c!p9NlH#GWNnEFCn}!W+Mhg0+L%R((*(X64=@N!F{w;zfU+hb-C}6|8 z4NDCpTSD{St}nxEDZH-9k~bX&3R`5tE{eRB_pjhH&P@z@T2E?5a(o=RaqldCb_`A@ zG_Om(S7>OEun{)&8D6mzLQ<JWn`JVTWXV;`ir(&tXB14JQ0^ zHR0%7&0GQofe=JXHe)y9%DOcL&U)2F9W}0u<1NDscC%aNlPNRaykU{6S-1P+@y@n> z_SUTH^Ul^fiSEeR)?2hOfRVi1*X(*j0pR?J2VgcpASz5BzDDai3}EtR3m8fiMs2C! zba6Z`{ur+&GJIy6cq&|VQ5aB^gh%SI+u&6QBCakEZnx0*d9gS2z&6HOxFJOzOhtBF&>H?ABC!57D5A0KA!I!v%lZuYsKzUZnAKh z>;Cg$dg*3tSu#wR9`VDmJ!1jt>zR=lFrCCK0Y$M?B1;5abzA`OWE13dV;Q!xTUNR1 zAOC$Q`0>QKX8q@wSuv|`MbRHVkU{KQ1KtswC0AuT8v1kSvI@Bc)jLzM9}(sg)2d+nj< zIarmF6o!3)8G%6{0KM~j4N_bFE5iWNGhVr>0PmVmj#jGeKM#W(m40oo%~vwtSB{QW zaMLeK!b_byy6JwKdnFZ}avItB+eTPVR%iO?#`EylQSLj`r+wK+{67mrt@`A|^f>-= z1#kMX;;*Xi)RJ!!nI1LNQ_ug|GYH15e7^WX9tNHlu?J88pT|NV8xI%m{%0KDtf;-) z1OEGZ@=Mn3-;V=}@rI%HKYxIH;w3QnpI>AtFoA&n`(oJs@7VOie;u%#0IdJz@8KUw z|MOl*^z-IhG5_Z!_vnA;H2$|frgYY(0-O53TQ>i3gX2HbhA@Ph{Vyw$F8=R|y67kV zyRl|bTmRkIVp*5}Zmc##&HoJci7i_He}0iA>H7a4^Z%kvE4cB;`=7&+zgl^%xw2~u zfNh}`bj{!S|7k-O-~&GHnunwfDLw_;$C!jPED%_5XjvN_wd1=^?= zu9gE(s5#VN?CF_XF?C^Wy+qIIw1naBR!3CGr##@WBXkk0w#}}rI`qT)$cNEKs=xls zN5$iV)iOZ8o%H~(G3Mw`T*HB4oAX9u)&Q_Is?7cOf!^PVyQyoS8DLxi(8~5k?%TF=3EWud*;_1|Qo@Oh#0IZ`ov6^P6eTB8e13q8x}45mfqKG z%?~ZNb;q#Y)V{epKq|K@%`IK+m5iR}^3=*4zRx&wRV~-%zTtS*dF4MUOfn~L?K1MB z6;O7+4I}j02aY{e$b$OjqG#{A&0;|N&jMGkU{I0^M)(pg1ahC}56t!$7~$PQWeLE= z%ApNRWHCqA$7BA)mebA)E;NhLm-$S?^rK*LGUpnDhW#gXAqg>lk=vZw`3K2WMFug= zFTrP)=R7+VP^Pg-Ce?&i@RdqxY9fX|+-5Z~dMP3>W)7uC2R!k2u34WfF-409;4M-F z&JB@55lW;@89)y;h6{7U&j4@M@af1=fEtg&XNPHe*nDww1(=+VxZl43R`7{>-PyVO z1iZK}7!jUjNIw)?3&e&%7+rH}f5UN&>{D2B2xc)6p}v57=HlvPu9l+sJqktdi`13; zkklWz!H6l4+vI`~iG)ttqgVj6Yg`ZR=lV{4gfyLd<%3t1!LS(Op;D={e?eqTG#DnBK)U@BR8eXg}q+bWR{}skz{IU0L-`K7c#==l0 zw*+C?8WI${BhHD1@lv~c*D?p~8$<8so3q!aS)ki9v=|firveIj{t*eoQcB2fHa0Ok z-hkh8KVcf#b5JhCJW=pkDiHWe$g7n#{n6VU1U!kN=*K&H%&HfpzxVZVAdvZhGkMBF zaPy1=sLRV^6cYEU8vwwnJ&C9;4t++N1_OjScVtEz6;kod@Y~lTB}yKQ%KhOY+pI`_ z@SW15dV*Ak&7xTI9+YJgLyUiiypMGlAD;q1mNWo1q5Ot~&c*T%ZWh^&0PK==T5ySh z44ge~bPQN7wS55>0>sRdNt$4i7uLmd*a0rFf*OAuUcrSZ#sg3;|2*5a(sqkU{R=?W zH(@d*2V7ilOU8)75afrKE1^KuU{ZfnDk|pa#YXrhcz)U z-g%E>)CjAbRZguDCjnNMu;^K!yr+#X*Er$peKK;PgHKNZZ8!kXx7wkhGE)tZJ*Erd zpgA=KmSv#b1ZbxGBlF7eqs3(o4xi?gaxL-ssEPR!FUF3(bp=eD#e)-!=WZ9!LW8v@ zMt@R5#*RW0UbXer%X(<+Cvd1ur@0dfX&{)xNCE(BtOn@9*dv2J_7^@(>l07uwg$qp@`gsEt>`W-DxN&qlQ&ClW_>IqvCAgQia=UEpK-#s}sxA)B9Aks~z-fM( zSzR@hE*-C_m}(m}C{nmHTKDwgfiC6@U1myLWDou$`W5a4=hxtdi7Nx;>o_VqUny#t z2j-FZ?xgp^O2ojMpN!eu-aD$5Ip8B{VN~7cDfI)N%H%`W^i5ZId_8<&^x2HOliV*U zxun6TKzrPP&pvyjzbhJEH$!(AFRY*<`CXk{E!eV=jn~ zVy-T(HU)kFO)%p3#iH9+^T%(ev>B=y)@ebo!JwhlN6EU>Rhwuq_Ji}M8x$C5ccs(`yiQskz#*%m287$(2+B1U+FW_MA_cNGT^ zvFu?Tlv)uOa`7?dO6qFQkKc->Y&a~k6VYDqwwv8}Tzy+a>aQM$Y?syaz=|SCUjV&) zH3Q#N`aLJVmbHs3HbANmPZ_|YDPg_wo;kZJ3OT%x?sJ3g-uiXFh72RngPE!j9-2&b zOzCJsKnCq`{wz6$3VJ=Rc>lKTH@`At4FmgIstfk_&otQ?s-sn`+S*-e^QI390J7jq zE%}kJfH-V+6NR#GUZhDd_gO$W?roGqdYy&#T~4VK4Ih@JJ5OT}6Mi03bm(XBj@y>j zLu?w>q=dBUu*v;|tL;*tZ!dDY+g{auwAsJ9ayX^F(&Jw};~`!}#`qN(=AB>bvH|Km z?OXRY^EEDYU{R#=6gq|J^?@7Gii*;kQ8#hV!5|2rAySK`k^8#En~9t6!L8*9YYF|r zjx(pz_Wt?Eo2b<C?lXRt)U#pl1iy ze$g$*u~=(n(zI26-Lq=(-ujny2Zz4zG7ewwbtLy6c^ zhL&uX;V}jmm|!k(#5bk2%Is+!>!G~HW5+>(yiRm@?~q@ClEbx28q3jtD|W*AcP%vR z-AGiq%Zpz}>pSzmm1lWy)Vg1pHD{&|lvl=#(;gGTGc2q9&}#TMv5bDn(29X_{j(B# z%N|9i#KwXeW(8v8vu11?)@zysnfK*~Tn|Q6y#yAq_2J^*{plbOc9k8|r1M$5E~D#T ziJKo-$7-KscDn?;+*o!kcowroAiye+cgQ4lzl5SAKr4N4nZfS0fq*Rx);ow-6%x#6 zXua>Cw6v&1slS6ctd=B2U_f0#UHBDYWjghfLb)fbE>5fhbX!m{TI6m&`W!>uT!dyUDIL&X3T;=5b9wwQreroJzN5eXmx)Fc7Z=vkP&$l8*L-k!K7|s^FE~j4A`))k@BRbRUS! z$KH5A*XKe8T)RVJG!CNn&I|5&P`K(LGPC|9V6c* zP|8`>0`cLk>^?5Kr73rzHBownye753J+l{zXUYS$Zj)-*efKAn< zjI%P*?5Jjs7IV9ieN)=~j7?Id_Re zlHzU7z>jo%Q3K|4vGrrk#!mV`Xg$NJJHc$l0zB(ipY{6tg^Ew_r2003iB8HfS z;ot3tIB0?KT~qiQq6f(CRjj&nZ=fuz55ra5kw+y6y>0#hr=r+9))8u^DFqN6jWGJN zTpRPC;d8(MqR!%R+b=(`@^m@}+;n`aegF08C2rOegV=f`H(GNhaq(xslEITQBspEJ$ zeG560=kXgvnfKsgtf}|Md#Iufgo-F0wxvU1_*RCoZj#W|F5U}er``t!3Bs(K5m*2vlf^-sM(FQ`* zVpe?WCs|rQJ_X3&b*Lc-s+(7^^9V`rf)GWaM=y}rh|By~&A3X$*QeZX^-t-@tFmD2 zrp3&v6=ob5Lgg!WZGPoxaDvI}qNC>T_siz6QwYbtvO^KKOP+LW$) znQI^iR*Kr?g$y$*m1dlmvmp9<0w7Vs-FJ+8g9Eu9q=O))$B!i4_V@igQsAaTszHoU z5htK%l82HQSkNDNhY|V@L>r`vS$(|R=*NIReKLtTc}{bWyO!&R zJA*@zU5*pAnjC7iG9)2s*2*%9YBwb}a&2b3g~s0Bp`gRoj0NH}dy((WlJh-O<7;lL z$KKg7Ga9+LvHFj%4pcoZeyg3*j8RGh#}`&__b1@#bB0p+S3xyKX>$V|bLzl5CN5l;z*tHNe#<#hk#mYn zY^Z%2&K~Q~!fEF>4y~!rZ4)s1$3AL`BS4&GPBBoKvAY}dF0*s~t%sw~)~AUBomnGO zKW2koU)@iV3wV{={es(F465k@4hIPYC7qmE(<+t9T~X!zi@97`?zU35(_ju(Rdi!1xnIxX3$0Xx5&7bAT)n7b za0PCC4cUN~EQeJeYcS=mq{^~duZzGxZ~GSgG%7Jvyf6pf zMGWxIl3jv2rEfQ-3xGPoLyl zRlr1Z%|(IX)9W;Wm;d(eYnDhg1xSVQ0blh+Kc#|`(0+=fZW~;k!PdS)VV|*TE+^;> zfndaaZeodxu||8nzyacj=F4wY2_$i?4EWT(MB2qx0{<6#Zygoo8orH=qN0Kzjie$1 zl7e)rbaxL3NJtMbbQ#o80s_*VLr6C$Fd*IC-5?!9d=Go?-}%=0|6A*vwa$6}al>Zb zdEV!_^SZD5ekoU2+lJSo0{;L;Or*X2^H!`=MkGR>j-H|+h4J$8t9sIf{glII4U7)Q zALY1sJB6xK!!#AC-j@&1oR%M3dw`lC#8!l%T9taCMOS~1D%seOS0h-R7s{i`KP*-W zc!{!6%9S#0WM#`+RpJ#hls%rk;$BnT7!**6cI1!`rSRf5)?GL|WSIexoaV zNsu@zK%eRz@Qn`!CePzdW*K9X_Apyt#L;fnK1y^{ zS9x9sghO-rPP%H2y};Picx}tT?X-uJ_3lOt8^w`pDLl5tZhI?4Q2x9IN* z-dcssd7gqjDM z_%L;E^XOTElNK+G)NSOwiNn}XBjbIHaXfGO4YUHZLdnvYql}5@t@F5)8wvk?%%Y(N zbj+nIpD$uRersrF_k`QijQjIhr}@&2!Cl|}J`u4clbb2KW3Ob}KsDxvS2RWd&D3nW zLIDPbwxA*EVOAS)?~_{K=m&(mGOdRSfL)$s-N*CWq!Pa0YyYgX%Z|Ba7rq8DQl+a= z8E)D9s4Y$AZkfgHUUZmuFO>ZOrKouEtaDP{W%8gw$)qfwc=3*;YrZE|JvS{2y+yC< z8PZCZ`nffTO7e=M@KJ1!0@=q+%J=NQ1IE|p2UF80{;OY?1HJxA`osJd)!&nCA2*B`8zv$Ke3uaS6ca?gRu;4QbaV3?l0`rfg!-P!^B$ z7?-rpv!nb!_Q|5T7%X8lWvae`*)6A4n0x9h(M_Ianmg+aNcRUto_CdXGm^@>h8qy6 zBo-f=f?Nqzy9_i|Ym(J1M9kFtt+xMy+J)YtoZKM*F7*u58W^?H45U?$?|U)51eu5H z7e&eizVu;(P!9j*xg*B9rLQ3? z`*!(ts(PZBQN*cO6AzVFdXkt)y&<7Hx*M^B^t9e9bVzfY@mBZHR89?___|X)FwRtv z=h3-0Dq&SGt2mUlbjWf!UovzmY#SHmCB=Er4CZm^z-h46( zP26g1+zp)%WV&MUq?UDthfsDrpz4p>}7G^#H15uQ2JhIX(E^!`C~USnuVX zd%2ogL05CEBI{Dl2VT1K7S;O^`edhR-)p^g!n+|SIw4V0Y|9@>&E!x{I*u`v{-e;G6?Ar;6^;ID#QdEF*05fSbPNxPd8T zH-ZiydR=a*8h&RhDlB_>vEZWILg-KiPc2=m(mjg_G6&wNtjBqluoeNmq2BNnw%&u; zMUsb|w1N<4vUUDPmWH0@jPuV%3e?Yzhc@{U__=bAQ=fnnPJtOvgi1FM*;KorH1X&B zGa5VUAv+#9KOF5{Dc|mu_wKR5a7rArsx%&baghf46=Nxl9aPfLLDbrL?rfw^EaHxP;Vk{{lUiA`gf&nI@8V<0bLd_@eGDx@KG*u~?bH2YK4stc;}@nvXanikDn0a?G=xCj z+jwaIw|T-+Bxw#HVe`pvMR}g8t{8J{!D4^$15J}m)~#Gr2kgltYTCw~&C>@fbh@NF zj|4+6m0{|d8H{3SoAEY^rXQ9U52G6$48&!d7^Oqh@KN!7w|L`tsZOL(o7LXd$;cV5 zRWoRVGgZfIM&0lcT#i|@?t17b`Cu|4DonkOI*!m1f1z}X0BWm#k%XCdqLUnDeAvNW zfchJ!HO+SE|CI#)n+nxa;2NRUGEOEp<|}TXLG;S9U8``-LsUtd833oJvQ%XR(Nr=BxVtp-b3I-vNas&3f#-OS0O9u$iCn zPIpIf0e$EwX z-A{g|YBP;JFt!5zD|_CoDC@gAtUP4&nHq1apj7-2+HGKk$xM&xot5=Bmn9Z2Q{_Ao zqemk(>F>X*2#VwUOJNJ3o05A;NS2vSZ*XX=^ab(ez8BgtfgziP4ysj+)1;wCv!2<7 zMWF|TWqaW)NDVuLl_-Qbk+S)7CcKaJt{CI{TF5A#Ki1v%h>D zc`u;fZ4DFyPdbOuIua);`9VhW23=hN8XuDL3qH7WWncCR z2L;>_=PR-eP(0!~p9UZmoo0l7Bwg|~*$KH@QW0Z>{ujR_HudcNO5DVoh6O?4HmLAs z$@IMM1sm-YVDsD0=5~G<5sg9r)uU&-z6Re*RkPy;yY?bw@MvP!#0xt5@lrs!essCv zBH6)=QJ*I{Xt%+gqV^$jq+LYqq9^X6%lZTQ>|srI+$vwSq)8OX$yk6i6~7Pbv+=u{ zzC2liR?F>7QiTUYvDwo1~B zb+OT?)uivEX{nPjNyzcMU*6)Gqt+hs8~O|$5u14qM3HA0y}hOEq|b|BTe8rKJHe=i z33@DwHaIi=l5x&X-XeAN3+2MQE8vT*88h3y|Ib773+HR-O! zWgc%zK@<(r!Z@Qn&rvmT)rT|4v*;?cOwnVOL8I~m&K*l%TfQj%Y_tLqK_}LvlEqm@ zTH^RqI|}DwK@sO|iUXy2ua(#1nycGF%2fwrfmZn0$%K*vlN($QYeJep&rsg}hNd^) zL+IJVlsB}sx5woDUDrt80+nVZu{-g!HVve$I^_5MNF~k{rMU)5JyY)}eww%%i@N(B z7f*=A1$N`)6^lOS!ERJJjqt z3ieb64y@g`W35I1be34GGCz0E%I4LdO}g+%wh|0>#SV)0oF$Y@v+QM@=VB*oi(1zI zP+6_1;cA_8_!e}v#sQ*Cs#>-Aw5?!IhJ<9bLa?~ftu>X{aJSmfic-CDN+T8gE9>Ca z_TbhxZh8}QS!z$L*kOvxi$@BCJGIM!h}}PlHI?5M#RgvEE^<$|<`*zdJ0oUmqkIP% zN32Uwbwvn9P2mQ`o!qm$mcZYnB#48Wi`?I&)Q?*2G+6h~`{q=Im9*ER-fP~0NCFs2 z)V87LZQHkRtvpnc-}P)b_2{tVtLe-ElmnU-#(pN9l9Gn`^ICzJsH}QNa>5`qArvdc zNyX=`Qsu+gzY}Q5>Ad5T95UWA#i|r-lC->uiC_P8{S+gP4t5p~{ucSO+Zu;=1s>IX z>sy?^CbTH>xcSny+4`n)p#IF9pTYAvN@AEJ?H@%iIF5Dla&e62};`7&IO9!tnh z8+HWRk%r)`wVpK@3$0(B;>nP&1>2^E zGp%0J+{sQ`wH4jsq=zk`B{&XA4|&fK(|g8(+@#I)L9-^2M8Tt=jU-ivU3Q?2W4-+T z;f1IbH*gL}uJ*!~a|6><45?dztWtoCYF~YtSEm^bdYl-6D{rJIhpRA%3yjm%(9)?v zrdSV?BH0hhc~mA7WZcO412E7QMdEY3`P#emEk|!iFJ>;=L5oZA7{N>T5tvPITdnjo z?K-abxBL8Wrx~#~(R%dD7Y2Vi4oOS~f{6Y9J_CO0Zu_idIo)^^X^iyNQs;f98ft!s z*kX7yd-3-2{DA*C^#Oy@aPEbgr^ntaIv--#v_r{rqzVsM@gKQ8`K$&dcO44W;I^Rp zru2fU-NQ~s?Y@eyOFWt3QsD?*meuq)slqPo)&OgTdAiu&q{Qgl5#l#ZvT3Mi7gDC| zXd8aoaTAte;pjp=y502C{f~bzkBxkmgg=r@qO-T&L7y-oKJ!N&P7jW?>#hBgR$HZ} z?aq`r^K~WM`#AYE+t!RRf+3YYtZ<@|cj``PI!CLoLM@1>tGnR#GSHYPAD8@2|HH zBA_-3wDmZYEnHL#-7-b7z%xe8^v-5XEsjk&a~qq!l8DzwjxpMV9mULR2}d#!6KTKx z!XEb>G%5@L7BlPQi7pgP46KUiV_$$w(v;t){G}h zPdwiaV1b(VqP?Ec86@T)MOL^iC=U!WmEkFXx{5MZ@CV7T-*d)t1 z@@>=8I+#X|dku(eITn!fTFhS`d_gNvG)qeQh4{0_eqCGDJT zkBlU(#BfoitFIc}rOF-!RUF&k#lP()jolDz zG^Km%F7J%iK1O#!%=J~@8ok@{&X6;#%MxyIKgE z8}^xVsQ(DdptabUgww`mk_<<$XfV&%{ghUVZ8eR-s=Cq0m(Is?0M-$l$@x)t>GtUIB}nIJ>x~bEFt@m5w{1S=yya-e zX#(WO!rh~a$_$HCYMTCGbx>lM1rBln=v32kRRHpH!OWz=N3%85Tk(NS*c@-6Tbj`) zS#u5dxNmk3%mB-u7i9HH?+&3-j3wu;rV@)%M+9cl%vmQ^08=rx20a)V(nUpEwKI=Q z;4zz?-9dd1Qg4_M{Ck%VqlT~|wg68qh~vSM+O`^^qSwi`!At+j11@vIs>kyc1Anz- z&%=V{nI3D#^-h2qdPdI{rIcD6fJ7+;J^j6npMdJU{%ZF5}Bc~f=1U0ek2G;fX1U#*5pQ8 z;nK#SD*>RJkJQR+3N{Rb-P7EDKmv}?#nv1|)>UsSA4DTMO0x_Ooo2S> zG?!Oi)l852*1N`+x)1NE(k(KR0H}TMVELvO+M&7lQq3ufZGV2|WprR+HXdya$7O?L z7y0;$8deo4$0zZie$a2nr`b~Wxvg?H72{V3xE=f0oluNM1*+@Z@Sh!znty(n z&N^_vp=q_XB-<0MRwXr6&Z7%gkU3@&i!D`bI+|UeU3CuEI%gyV1td8Y$c1(_X^jFG zBGceFS}YpFZ_I_|tFF-{2uYspF`lMRRTRMBqWuF%yA)>a69= z_XkDhmEZZl%am+x+wgBi#W$7@UrsynKA^nw_?v95YYF+K4WNnbDdh<*6eojmQlD@E zy7`!76h(;#GBOVud0_&;Kn=S3w;CGWY?Be`s1BjJ2&wzkAbOAI$R!!{ zYVZya8ZTG02Mxpv?TSRwg%$MsHj!2(x1B8Hq%ysptqj~|=ukhWJdj3Z%rM(gK#gp_Y4Z7A3quCs1 zgDbS72FtxXYjzQqVMLtYD0t8c^>e1@_?#44rcip07viWnd3^3V{mWsC zsh;?eAj!kmT*-$ME>zw|oT2J3?&K{tl;(Ji(^p(Y9nx6wigHFIX}$v0yI+-nMhl>m zd(U(z0773_3EvI|teT2m+Z@jmy9mIr;eF}d;2+`jHPnm^EDG=k>#^$3;>@lAH&GrS zvR`p%Z%;Wo>V>H6G%_#V|FewsiF|NHFGnl<-3yXXcHs0UK+`CTUT6?ke<@|r43f8( zdtN;DFb!qsU}{lVKaVk9)>IQXJO)ztoI)gk&mR;ze=@#hv|NG<%@3=&ch8u1F$HC4 zEM0VE-@<*L5;)3IV8IK|6S?ib*ww9dk75yFndcv~7O{Z!&BTKk`vGMDJudB~?p1JP z-|w#~#PgRiy~oR4Fg+0CkCXBS1B|Ait(wzKS7$dDqpy_b zm2%^PQ6C5RYHkCT6rk(5HLjX$9@lJjkJ1C~-p#qz_6GBfm!G7_-7l|RZf@H*!-kdO zeqFI&2rFT;YM%LulVT#A%TPZUxFY8uO`OXy_ZL>2-nyD2zj)9)NQgiLmM{;DbHx<0ir!8gw)?i~f3QoR8-@q`xH zXW*Ojm@lya%W);i?`n9NkP;F@8YlBj*0xRIpGd4@KJ78 z>zdT=BlrDW`t@9d(`VZko=V{v{40AE9)k6zT}cS?G;s_Of;mtMhor5l%u^gOUVjPn z?GuhTv=CFg;x3tSA**Da@cixXAU*pI^Ha~nR~%9C;aBf%fRA5tX4i1so}J4|XtTBE zia9h$V|q|OT^Or%)9ynQPZ*!?HY4xPK81aq&0~P8W_5MmVg4ruguaHH(IkLoa~w|} zA^qqM5S*FL?E`yn0ex}h<&U{jUpkjN+5KkyQ6%lUM6-B*zl{EA{Di1@L+s(rv+reo zt8MdV3{ZAM${?;FOSyN7Aek8fqH1-($KK!tVaa;frG?xBDn8sq;62aGDv-R%t;+Vsy}kFYpj{-M%0=gVgM zavxtn|2xu8&kDO4GG_x~n7R9a{b3hu&#uO-{>q^90nX{3p4YJv)P=N^bw=`MiRuYH z^q2fSfDfU8(I+^|mCCMRGBlZ&o!(unMC-kc)f^iN>k9oHtwIt(6%AS?cEw@{b3zPb zN%@t-5ABZt@7zq{SuBV-N;%fmS0(C)>xKKFTsjy+<-yP2vaSZ1^Z4H3Z{3hs{sN|Y zG{*cJoSGn3-LLh>C;ob_iRxI;pdZlEh4o2*hD?YaqDJ1~vqw3p0-y}=NBQ672ZW>{ zH#yEM1+y4iliTK|M8V~t8?bVtn@<>!0_o-H|9;*XSEs9YvoG35cs0gNJO0RR{UB!B zko4m&MoaTY6W7Vf`%wh$Q2^kd;>L&E0`9?wv#R2`+{f2jpzH+VX;!GLa4ip!%m;UgK*rfB#=BCPS6zfmTox$Y|kW~gu3$!h=c8JZi za{Ms9EAO-&rLM1_B6Tmy-L{&pF2bA#g93DtJfgtOoR~K~WWa24v*9J?`H{1b-OS#u zUiY2pqo>VdeQE7wFhfHUOS`dEZ6TF~*uqJFE<0oN{IzyeuGaTR9#SkHQ@~ybfVx60 z0ykPXt7lZ}nGfzLBO|+zk*mdz#YY>rvba~}1m zp1PJo%<{$49N@kBv;i^mC7lKEd9K>aM6#C6-j-!1tw%j3lT-{9LLq>h@>H6Dt5jET(APRo=S_M& z4o;-7!Rcot{F$X%MhjJ%CbddB190@!LJ1~Rm%2<%1Z3}VPjDnlke4bo4bZBagw71i z#t38_SGUidlgdg1;jsc3A=5qjy)5lf0^KNxNwQh1Di)(QzdGYvLqA2&JNTz`gp@E@ z%HB+wu?Bk~9eet)JnpYCqTtzcZgz@JK$obw(Kr<^SJHz_MEllM^BAO0Tw^qekdGGd z76qWXH7gjmU6<^-a1R(LP(QZfz5<5RhqLf907%;ja{6(LKjYorYx_Xn$I$7^P++qh z%uvp%3|M!jCIg!d6pfOWb`z0=GpO%dZukJIf6ha-n~k6yZF12A6%EMa2pF7X;Mc{) zQQBF(Sj-Kv2f&|Xa}nDKT9~&uyFNNJ1HB+`3;zoK;iHlXvrgfQPOda(#R<;<3LMZ5 zG!xVvwPQ~$wr5O^q!LdViVx5W_&$`dl5?enEk}sy$ZK zyhC3g?ewx>SO&zOK7REMd;t-5d<8imjUZp-g#8Amh!%7rpbp#c4w4Kdi%boNo~y zV?S0}1bAQIl~K2<23zg&75$7;n}L`CRzo#K9P%y?mpYgObyLHR&5&$u_9i6gwmuLa zc>M)-MLf*?H!RRSgBI7LPR+xV_}(Jq7d3D(bdK0Ww2dx+;ufO$@=A*h|>`$FL zI2gY&KUuLs=>3duC9BnQ8Se9N!U3yuumpcIeYpylW-!euQ8zR&g}6l83H7t_(L&iP zvendn-d|9?ljR0R9tej>d zi5BFhaxxU8YDy!+YS7+JtpcPGr-_=eaYoP2btps{6g@Rg|EzwL1TxG z*OM@wS5&y)4h>`*I?g-82VvHW6A$-+e+sy3v;CHaut8~i)W&)WX=}*Y15_bs2g??W zTEYawYVaqjI-fd1paWSSG-b#|&Hm}kP8s%MxBeT`&nxHk)y%aa z@kuC(>OJq_pZC~79mL7NDF6CC%+(A43^2?ILUO}#a|5EsDCJd{CJ$(YZ0&SEI|v{? zoXoV-uc=ylKvAKC}X~&!9E+IQXM`JLOXe81U5Q}HTj)z&dvhVDIbNd&S z9MaxGj<$}d%NJX0R=grJ+ikMT2Uw{ns7(o!y&PXO0>iW3fm~o@IDmMuzvFQfDJx;A zIV#Wv=)dS)FyNy8j6crzasP|jrK$xp9!i_wMZgc7KGGYI#9d?+41S>3X5wou!(-F{ zoOT~fgCG=az%j7!?70Zmb+`RSd8{OsJS|#u{YHN4rW+AW9{V~60FqQTH2j=8DZ_$R zrk)s=fYDZ>84Pe1e<4I&hLKgzmDhz8YRO{0V8pcw7V= zB{nnoLLUGOh?3oqK_;U9+`EAl+TOixeq{kTBg04g$MFDa1I$hgy8XyCw{1hYUzpTH zA?;vX#A>SX+D~v=4a8VFWmQw|X->P|7*b`c6QwpGl%I!t=QeA`EN0Vzkd#fbrNhh} zl8F(@g)zQ3??G0kiJZ(H8jED+!3HAed0Q{G`+-yxeR$3uRG) z9WaapTv9-b5`9!Xuhmc(L@%-E!9|A20;nKeGtD=FDi<+Xcr69tV3J0X*kBMzdGgOJVzRc*1^6`vXoJ(7^G>1QKpRkmu=@hkDO|cd z?m*0mAU1lqc(nQz89fgfrY4}=0g}dc2e(iAI-6v6iR{8P7IiGUvMcgM2h<-0X#D3@t≫#$PDFJFLc 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 Z?8HEGwc>jCAhcHCx~73f$yJ-s{{T{SSwH{) literal 0 HcmV?d00001 diff --git a/custom_components/pdf_scrape/brand/icon@2x.png b/custom_components/pdf_scrape/brand/icon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..174460aa554381d479eb0aedd355499212f93934 GIT binary patch literal 18954 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 E0FJRxHUIzs literal 0 HcmV?d00001 diff --git a/custom_components/pdf_scrape/brand/logo.png b/custom_components/pdf_scrape/brand/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c2ada59a6f427bab89dd9a8d205cc155b4124aec GIT binary patch literal 38151 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

$v+QkkItJM@A+9N$0Ikur-1 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 eHT-{Ai7n9=-uj_)jO-Z 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 None: + async def async_step_finish( + self, user_input: dict[str, Any] | None = None + ) -> ConfigFlowResult | None: + """Finish this flow.""" + await self.async_set_unique_id(self.unique_fun()) + if entry := self.hass.config_entries.async_entry_for_domain_unique_id( + DOMAIN, self.unique_id + ): + if self.source == SOURCE_USER or ( + self.source == SOURCE_RECONFIGURE + and entry.entry_id != self._get_reconfigure_entry().entry_id + ): + return self.async_abort( + reason=self.reason, + description_placeholders=self.placeholders, + ) + title: str = self.data[CONF_NAME] if not self.title_fun else self.title_fun() + if self.source == SOURCE_USER: + return self.async_create_entry( + title=title, + data=self.data, + subentries=[DOCUMENT_SUBENTRY.as_dict()], + ) ir.async_delete_issue( self.hass, DOMAIN, f"{ErrorTypes.PDF_ERROR}_{self._get_reconfigure_entry().entry_id}", ) + return self.async_update_and_abort( + self._get_reconfigure_entry(), + title=title, + data=self.data, + ) + + async def async_on_create_entry(self, result: ConfigFlowResult) -> ConfigFlowResult: + """Next flow for create flow.""" + subentry_flow: SubentryFlowResult = ( + await self.hass.config_entries.subentries.async_init( + (result["result"].entry_id, "target"), + context=SubentryFlowContext(source=SOURCE_USER), + ) + ) + result["next_flow"] = ( + FlowType.CONFIG_SUBENTRIES_FLOW, + subentry_flow["flow_id"], + ) + return result + + async def async_step_process_error( + self, + user_input: dict[str, Any] | None = None, + ) -> ConfigFlowResult: + """Handle errors during processing.""" + await async_cleanup(self.hass, self.flow_id) + return self.async_abort( + reason=self.reason, + description_placeholders=self.placeholders, + ) + + def _async_progress(self) -> ConfigFlowResult | str | None: + if self.process_task is not None: + if not self.process_task.done(): + self.async_update_progress(self.pdf.progress) + return self.async_show_progress( + step_id=self.cur_step["step_id"], + progress_action="pdf_process", + progress_task=self.process_task, + ) + if exception := self.process_task.exception(): + _LOGGER.debug("Progress task exception", exc_info=exception) + self.placeholders["msg"] = str(exception) + if isinstance(exception, PDFParseError): + self.reason = "pdf_parse" + elif isinstance(exception, HTTPError): + self.reason = "http_error" + elif isinstance(exception, FileError): + self.reason = "file_error" + else: + self.reason = "exception" + return self.async_show_progress_done(next_step_id="process_error") + self.process_task = None + return self.async_show_progress_done(next_step_id="finish") + return None async def async_step_http( self, user_input: dict[str, Any] | None = None @@ -138,47 +231,27 @@ async def async_step_http( else: try: url(user_input[CONF_URL]) - pdf: PDFScrapeHTTP = await PDFScrapeHTTP.pdfscrape( - self.hass, user_input[CONF_URL] + self.data[CONF_URL] = user_input[CONF_URL] + self.data[CONF_SCAN_INTERVAL] = {"seconds": td.total_seconds()} + self.data[CONF_TYPE] = ConfType.HTTP + self.placeholders = {"url": user_input[CONF_URL]} + self.reason = "http_already_configured" + self.pdf = PDFScrapeHTTP(self.hass, user_input[CONF_URL]) + self.title_fun = lambda: ( + user_input.get(CONF_NAME) + or self.pdf.pdf.title + or user_input[CONF_URL] ) - pdf.close() - # Store the token in the config entry data - title: str = user_input.get(CONF_NAME, user_input[CONF_URL]) - data: dict[str, Any] = { - CONF_URL: user_input[CONF_URL], - CONF_SCAN_INTERVAL: {"seconds": td.total_seconds()}, - CONF_TYPE: ConfType.HTTP, - } - if user_input.get(CONF_NAME): - data[CONF_NAME] = user_input[CONF_NAME] - if self.source == SOURCE_USER: - await self.async_set_unique_id( - f"{DOMAIN}_{user_input[CONF_URL]}" + self.unique_fun = lambda: self.data[CONF_URL] + if self.process_task is None: + self.process_task = self.hass.async_create_task( + self.pdf.update(), "pdfscrape_process" ) - self._abort_if_unique_id_configured() - return self.async_create_entry( - title=title, - data=data, - ) - if self.source == SOURCE_RECONFIGURE: - await self.async_set_unique_id( - f"{DOMAIN}_{user_input[CONF_URL]}" - ) - self._async_clear_issue() - return self.async_update_reload_and_abort( - self._get_reconfigure_entry(), - title=title, - data=data, - ) - _LOGGER.error("Accessed from invalid source: %s", self.source) - errors["base"] = "invalid_source" except vol.Invalid: errors[CONF_URL] = "invalid_url" - except PDFParseError: - errors[CONF_URL] = "pdf_parse" - except FileError as err: - _LOGGER.warning("File/OS Error %s", err) - errors[CONF_FILE] = "file_error" + if not errors and (result := self._async_progress()): + return result + flow_schema: vol.Schema = vol.Schema( { vol.Optional(CONF_NAME): TextSelector(), @@ -202,7 +275,7 @@ async def async_step_http( flow_schema = self.add_suggested_values_to_schema( flow_schema, { - **self._get_reconfigure_entry().data, + **data, CONF_NAME: self._get_reconfigure_entry().title, }, ) @@ -234,47 +307,41 @@ async def async_step_upload( """Handle config flow.""" errors: dict[str, str] = {} if user_input: - try: - with await self.hass.async_add_executor_job( - process_uploaded_file, self.hass, user_input[CONF_FILE] + + def _process_pdf() -> PDFScrapeUpload: + with process_uploaded_file( + self.hass, user_input[CONF_FILE] ) as pdf_path: # Assign a flow_id for now as the file is deleted when we are done. - pdf: PDFScrapeUpload = await PDFScrapeUpload.pdfscrape( - self.hass, path=pdf_path, config_entry_id=self.flow_id - ) - title: str = ( - user_input.get(CONF_NAME) or pdf.metadata_name or "Uploaded PDF" + pdf: PDFScrapeUpload = PDFScrapeUpload( + self.hass, + ( + self.flow_id + if self.source == SOURCE_USER + else self._get_reconfigure_entry().entry_id + ), + pdf_path, ) - data: dict[str, Any] = { - "temp_storage_id": self.flow_id, - CONF_TYPE: ConfType.UPLOAD, - } - if self.source == SOURCE_USER: - await self.async_set_unique_id( - f"{DOMAIN}_{user_input[CONF_FILE]}" - ) - self._abort_if_unique_id_configured() - return self.async_create_entry( - title=title, - data=data, - ) - if self.source == SOURCE_RECONFIGURE: - await self.async_set_unique_id( - f"{DOMAIN}_{user_input[CONF_FILE]}" - ) - # self._abort_if_unique_id_mismatch() - return self.async_update_reload_and_abort( - self._get_reconfigure_entry(), - title=title, - data=data, - ) - _LOGGER.error("Accessed from invalid source: %s", self.source) - errors["base"] = "invalid_source" - except PDFParseError: - errors[CONF_FILE] = "pdf_parse" - except HTTPError as err: - _LOGGER.warning("HTTP Error %s", err) - errors[CONF_FILE] = "http_error" + return pdf + + self.pdf: PDFScrapeUpload = await self.hass.async_add_executor_job( + _process_pdf + ) + self.title_fun = lambda: ( + self.data.get(CONF_NAME) or self.pdf.pdf.title or "Uploaded PDF" + ) + self.unique_fun = lambda: self.pdf.pdf.sha256_checksum + self.reason = "upload_already_configured" + self.data["temp_storage_id"] = self.flow_id + self.data[CONF_TYPE] = ConfType.UPLOAD + if self.process_task is None: + self.process_task = self.hass.async_create_task( + self.pdf.update(), "pdfscrape_process" + ) + + if result := self._async_progress(): + return result + flow_schema: vol.Schema = vol.Schema( { vol.Optional(CONF_NAME): TextSelector(), @@ -300,45 +367,22 @@ async def async_step_local( self, user_input: dict[str, Any] | None = None ) -> ConfigFlowResult: """Handle config flow.""" - errors: dict[str, str] = {} - error_placeholders: dict[str, str] = {} if user_input: - try: - await PDFScrapeLocal.pdfscrape( - self.hass, path=Path(isfile(pathcheck(user_input[CONF_FILE]))) - ) - data: dict[str, Any] = { - CONF_TYPE: ConfType.LOCAL, - CONF_FILE: user_input[CONF_FILE], - } - title: str = ( - user_input.get(CONF_NAME) or user_input[CONF_FILE] or "Local PDF" + self.pdf = PDFScrapeFile( + self.hass, path=Path(isfile(pathcheck(user_input[CONF_FILE]))) + ) + self.data[CONF_TYPE] = ConfType.LOCAL + self.data[CONF_FILE] = user_input[CONF_FILE] + self.title_fun = lambda: ( + user_input.get(CONF_NAME) or user_input[CONF_FILE] or "Local PDF" + ) + self.unique_fun = lambda: self.data[CONF_FILE] + if self.process_task is None: + self.process_task = self.hass.async_create_task( + self.pdf.update(), "process_pdf" ) - if self.source == SOURCE_USER: - await self.async_set_unique_id(f"{DOMAIN}_{user_input[CONF_FILE]}") - self._abort_if_unique_id_configured() - return self.async_create_entry( - title=title, - data=data, - ) - if self.source == SOURCE_RECONFIGURE: - await self.async_set_unique_id(f"{DOMAIN}_{user_input[CONF_FILE]}") - # self._abort_if_unique_id_mismatch() - self._async_clear_issue() - return self.async_update_reload_and_abort( - self._get_reconfigure_entry(), - title=title, - data=data, - ) - _LOGGER.error("Accessed from invalid source: %s", self.source) - errors["base"] = "invalid_source" - except PDFParseError: - errors[CONF_FILE] = "pdf_parse" - except (FileError, vol.Invalid) as err: - _LOGGER.warning("File Error %s", err) - if isinstance(err, vol.Invalid): - error_placeholders[CONF_FILE] = err.msg - errors[CONF_FILE] = "file_error" + if result := await self._async_progress(): + return result flow_schema: vol.Schema = vol.Schema( { vol.Optional(CONF_NAME): TextSelector(), @@ -358,10 +402,8 @@ async def async_step_local( return self.async_show_form( step_id="local", data_schema=flow_schema, - errors=errors, description_placeholders={ "url_file_integration": URL_FILE_INTEGRATION, - **error_placeholders, }, ) @@ -383,6 +425,12 @@ class TargetSubentryFlowHandler(ConfigSubentryFlow): data: dict[str, Any] = {} pdf: PDFScrape + preview_task: Task[str] | None = None + _progress_task: Task[str] | None = None + + def get_config_entry(self) -> PDFScrapeConfigEntry: + """Return the config entry this subentry flow belongs to.""" + return cast(PDFScrapeConfigEntry, self._get_entry()) async def async_step_reconfigure( self, user_input: dict[str, Any] | None = None @@ -409,7 +457,7 @@ async def async_step_user( config_entry_id=config_entry.entry_id, ) case ConfType.LOCAL: - self.pdf = await PDFScrapeLocal.pdfscrape( + self.pdf = await PDFScrapeFile.pdfscrape( self.hass, config_entry.data[CONF_FILE], config_entry_id=config_entry.entry_id, @@ -422,30 +470,59 @@ async def async_step_user( if user_input: if not re.match(REGEX_PAGE_RANGE_PATTERN, user_input[CONF_PDF_PAGES]): errors[CONF_PDF_PAGES] = "invalid_page_range" - try: - self.pdf.get_pages(user_input[CONF_PDF_PAGES]) - except IndexError: - errors[CONF_PDF_PAGES] = "pages_out_of_range" - if not errors: - self.data[CONF_PDF_PAGES] = user_input[CONF_PDF_PAGES] - return await self.async_step_regex(None) + self.data[CONF_PDF_PAGES] = user_input[CONF_PDF_PAGES] + self.data[CONF_OCR] = user_input[CONF_OCR] + + self._progress_task = self.get_config_entry().async_create_task( + self.hass, + self.pdf.get_pages( + user_input[CONF_PDF_PAGES], user_input.get(CONF_OCR, False) + ), + "step_user_get_pages", + True, + ) + if self._progress_task is not None: + if self._progress_task.done(): + if self._progress_task.exception(): + if isinstance(self._progress_task.exception(), IndexError): + errors[CONF_PDF_PAGES] = "pages_out_of_range" + else: + errors["base"] = self._progress_task.exception() + self._progress_task = None + else: + self._progress_task = None + return self.async_show_progress_done(next_step_id="select") + else: + return self.async_show_progress( + step_id="user", + progress_action="getting_pages", + progress_task=self._progress_task, + ) default_pages: str = "1" + ocr: bool = False if self.source == SOURCE_RECONFIGURE: default_pages = str( self._get_reconfigure_subentry().data.get(CONF_PDF_PAGES, 0) ) + ocr = self._get_reconfigure_subentry().data.get(CONF_OCR, False) return self.async_show_form( + step_id="user", data_schema=vol.Schema( { vol.Required(CONF_PDF_PAGES, default=default_pages): TextSelector( TextSelectorConfig(type=TextSelectorType.TEXT) ), + vol.Optional(CONF_OCR, default=ocr): BooleanSelector( + BooleanSelectorConfig( + read_only=True # until we figure out tesseract app. + ) + ), } ), description_placeholders={ "title": self._get_entry().title, - "pages": len(self.pdf.pages), + "pages": self.pdf.pdf.page_count, }, errors=errors, last_step=False, @@ -455,33 +532,32 @@ async def async_step_user( @staticmethod async def async_setup_preview(hass: HomeAssistant) -> None: """Set up preview WS API.""" - # try: websocket_api.async_register_command(hass, ws_start_preview) - async def async_step_regex( + async def async_step_select( self, user_input: dict[str, Any] | None = None ) -> SubentryFlowResult: """Get the regex.""" errors: dict[str, str] = {} - text: str = self.pdf.get_pages(self.data[CONF_PDF_PAGES]) + text: str = await self.pdf.get_pages(self.data[CONF_PDF_PAGES]) - if user_input and user_input.get(CONF_REGEX_SEARCH): + if user_input and CONF_REGEX_SEARCH in user_input: # Validate that it's a valid regex try: matches: list[str] = re.findall(user_input[CONF_REGEX_SEARCH], text) # Do we get matches? - if len(matches): - # Forward to matches + if len(matches) > 0: + # Forward to sensor self.data[CONF_REGEX_SEARCH] = user_input.get(CONF_REGEX_SEARCH) - return await self.async_step_matches(None) - errors["base"] = "no_matches" + return await self.async_step_sensor(None) + errors[CONF_REGEX_SEARCH] = "no_matches" except re.PatternError as err: _LOGGER.warning("Invalid Regular Expression: %s", err.msg) - errors["base"] = "bad_pattern" + errors[CONF_REGEX_SEARCH] = "bad_pattern" - if user_input and user_input.get("page_text"): + if user_input and user_input.get("page_text") and not errors: # User wants all the txt. - return await self.async_step_matches(None) + return await self.async_step_sensor(None) schema: vol.Schema = vol.Schema( { @@ -498,7 +574,7 @@ async def async_step_regex( schema, self._get_reconfigure_subentry().data ) return self.async_show_form( - step_id="regex", + step_id="select", data_schema=schema, description_placeholders={ "title": self._get_entry().title, @@ -509,13 +585,13 @@ async def async_step_regex( preview="target", ) - async def async_step_matches( + async def async_step_sensor( self, user_input: dict[str, Any] | None = None ) -> SubentryFlowResult: """Get the regex.""" errors: dict[str, str] = {} - text: str = self.pdf.get_pages(self.data[CONF_PDF_PAGES]) + text: str = await self.pdf.get_pages(self.data[CONF_PDF_PAGES]) pattern: str | None = self.data.get(CONF_REGEX_SEARCH) matches: list[str] = re.findall(pattern, text) if pattern else [] @@ -529,7 +605,7 @@ async def async_step_matches( else: value = text preview: PreviewSensorEntity | None = None - errors, preview = _validate_step_matches( + errors, preview = _validate_step_sensor( self.hass, config=user_input, value=value ) if preview: @@ -541,11 +617,20 @@ async def async_step_matches( errors["base"] = errors["base"][:255] + " " if not errors: if self.source != SOURCE_RECONFIGURE: - config_id: str = str(len(self._get_entry().subentries)) + unique_ids: set[int] = { + int(unique_id) + for unique_id in { + subentry.unique_id + for subentry in self._get_entry().subentries.values() + } + if unique_id != "document" + } return self.async_create_entry( title=user_input.get(CONF_NAME), data=self.data | user_input, - unique_id=config_id, + unique_id=str( + max(unique_ids) + 1 if len(unique_ids) > 0 else 0 + ), ) # Was there an issue? iss_reg: ir.IssueRegistry = ir.async_get(self.hass) @@ -555,8 +640,7 @@ async def async_step_matches( f"{error_type}_{self._get_entry().entry_id}_{self._get_reconfigure_subentry().subentry_id}", ): ir.async_delete_issue(self.hass, DOMAIN, issue.issue_id) - - return self.async_update_reload_and_abort( + return self.async_update_and_abort( self._get_entry(), self._get_reconfigure_subentry(), title=user_input[CONF_NAME], @@ -626,13 +710,22 @@ async def async_step_matches( schema: vol.Schema = vol.Schema(step_schema) return self.async_show_form( - step_id="matches", + step_id="sensor", data_schema=schema, last_step=True, errors=errors, preview="target", ) + def async_remove(self) -> None: + """Handle removal of this subentry.""" + if self.preview_task is not None and not self.preview_task.done(): + self.preview_task.cancel() + if self._progress_task is not None and not self._progress_task.done(): + self._progress_task.cancel() + if self.pdf is not None: + self.hass.add_job(self.pdf.close) + @websocket_api.websocket_command( { @@ -642,8 +735,8 @@ async def async_step_matches( vol.Required("user_input"): dict, } ) -@callback -def ws_start_preview( +@websocket_api.async_response +async def ws_start_preview( hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict[str, Any], @@ -670,13 +763,13 @@ def ws_start_preview( user_input: dict[str, Any] = msg["user_input"] @callback - def async_preview_updated( + def async_preview_callback( state: str | None, attributes: Mapping[str, Any] | None, - listeners: dict[str, bool | set[str]] | None, error: str | None, + domain: str | None, ) -> None: - """Forward config entry state events to websocket.""" + """Forward updates to websocket.""" if error is not None: connection.send_message( websocket_api.event_message(msg["id"], {"error": error}) @@ -685,18 +778,21 @@ def async_preview_updated( connection.send_message( websocket_api.event_message( msg["id"], - {"attributes": attributes, "listeners": listeners, "state": state}, + { + "attributes": attributes, + "domain": domain, + "state": state, + }, ) ) - page: int = 0 - value: str | None = None + value: str | list[str] | None = None flow: TargetSubentryFlowHandler = cast( TargetSubentryFlowHandler, hass.config_entries.subentries._progress.get(msg["flow_id"]), # noqa: SLF001 ) pdf: PDFScrape = flow.pdf - preview: PreviewSensorEntity | None = None + preview: PDFPreviewEntity | None = None if step in ["user", "reconfigure"]: user_input[CONF_NAME] = "Text" user_input[CONF_ICON] = "mdi:file-pdf-box" @@ -704,14 +800,25 @@ def async_preview_updated( if re.fullmatch(REGEX_PAGE_RANGE_PATTERN, pages) is None: errors[CONF_PDF_PAGES] = "invalid_page_range" else: + if flow.preview_task is not None and not flow.preview_task.done(): + flow.preview_task.cancel() + await flow.preview_task + flow.preview_task = flow.get_config_entry().async_create_task( + hass, + pdf.get_pages(pages, bool(user_input.get(CONF_OCR, False))), + "pdf_preview_pages", + True, + ) try: - value = pdf.get_pages(pages) + await flow.preview_task except IndexError: - errors[CONF_PDF_PAGES] = "invalid_page_range" + errors[CONF_PDF_PAGES] = "pages_out_of_range" + if not errors: + value = flow.preview_task.result() else: pages = flow.data[CONF_PDF_PAGES] - value = pdf.get_pages(pages) - if step == "regex": + value = await pdf.get_pages(pages) + if step == "select": pattern: str | None = user_input.get(CONF_REGEX_SEARCH) if pattern: user_input[CONF_ICON] = "mdi:text-box-search-outline" @@ -723,32 +830,38 @@ def async_preview_updated( ) if len(matches) > 1: user_input[CONF_NAME] = f"{len(matches)} Matches" - value = ", ".join(matches) + matches = [ + match if len(match) < 30 else match[:25] + " ***" + for match in matches + ] + preview = PreviewSelectEntity( + matches, + user_input, + ) elif len(matches) == 1: value = matches[0] user_input[CONF_NAME] = "1 Match" else: - value = "No matches found." - user_input[CONF_NAME] = "?" + errors[CONF_REGEX_SEARCH] = "no_matches" except re.PatternError as ex: errors[CONF_REGEX_SEARCH] = str(ex.msg) else: user_input[CONF_ICON] = "mdi:file-pdf-box" user_input[CONF_NAME] = "Text" - elif step == "matches": + elif step == "sensor": # Generate preview regex: str | None = flow.data.get(CONF_REGEX_SEARCH) if regex: matches: list[str] = re.findall( regex, - pdf.pages[page], + await pdf.get_pages(pages), ) match_idx: int = int(user_input[CONF_REGEX_MATCH_INDEX]) if match_idx >= 0: value = matches[match_idx] else: value = matches - errors, preview = _validate_step_matches( + errors, preview = _validate_step_sensor( hass, config=user_input, value=value ) else: @@ -765,65 +878,94 @@ def async_preview_updated( ) return - if not preview: - preview = PreviewSensorEntity(hass, config=user_input, value=value) + if preview is None: + preview = PreviewSensorEntity(value, user_input) connection.send_result(msg["id"]) - - connection.subscriptions[msg["id"]] = preview.async_start_preview( - async_preview_updated + connection.subscriptions[msg["id"]] = preview.async_show_preview( + async_preview_callback ) -class PreviewSensorEntity(SensorEntity): +class PDFPreviewEntity(Entity): """Preview entity for frontend.""" - def __init__(self, hass: HomeAssistant, config: dict[str, Any], value: str) -> None: + def __init__(self, config: dict[str, Any], domain: str) -> None: """Initialize a preview entity.""" - self.hass: HomeAssistant = hass self._attr_name = config.get(CONF_NAME, "Preview") - self._attr_device_class = config.get(CONF_DEVICE_CLASS) - self._attr_native_unit_of_measurement = config.get(CONF_UNIT_OF_MEASUREMENT) - self._attr_state_class = config.get(CONF_STATE_CLASS) self._attr_icon = config.get(CONF_ICON, "mdi:eye") - self._attr_native_value = ( - value - if not isinstance(value, str) - else (value if len(value) < 255 else value[:251] + " ***") - ) + self.domain: str = domain + self._preview_callback: ( + Callable[ + [str | None, Mapping[str, Any] | None, str | None, str | None], + None, + ] + | None + ) = None @callback - def async_start_preview( + def async_show_preview( self, preview_callback: Callable[ [ - str | None, - Mapping[str, Any] | None, - dict[str, bool | set[str]] | None, - str | None, + str | None, # state + Mapping[str, Any] | None, # attributes + str | None, # errors + str | None, # domain ], None, ], ) -> CALLBACK_TYPE: - """Render a preview.""" - errors: str | None = None + """Start a preview.""" + error: str | None = None try: calculated_state: CalculatedState = self._async_calculate_state() preview_callback( - calculated_state.state, calculated_state.attributes, None, None + calculated_state.state, + calculated_state.attributes, + None, + self.domain, ) except ValueError as ex: - errors = str(ex) - if len(errors) > 255: - errors = errors[:250] + " ***" - if errors: - preview_callback(None, None, None, errors) - + error = str(ex) + if len(error) > 255: + error = error[:250] + " ***" + if error: + preview_callback(None, None, error, None) return self._call_on_remove_callbacks -def _validate_step_matches( +class PreviewSensorEntity(PDFPreviewEntity, SensorEntity): + """Preview sensor entity for frontend.""" + + def __init__( + self, value: str, config: dict[str, Any], domain: str | None = None + ) -> None: + """Initialize a preview entity.""" + super().__init__(config, SENSOR_DOMAIN) + self.domain: str | None = domain + self._attr_device_class = config.get(CONF_DEVICE_CLASS) + self._attr_native_unit_of_measurement = config.get(CONF_UNIT_OF_MEASUREMENT) + self._attr_state_class = config.get(CONF_STATE_CLASS) + self._attr_native_value = value if len(value) < 255 else value[:251] + " ***" + + +class PreviewSelectEntity(PDFPreviewEntity, SelectEntity): + """Preview sensor entity for frontend.""" + + def __init__( + self, + options: list[str], + config: dict[str, Any], + ) -> None: + """Initialize a preview entity.""" + super().__init__(config, SELECT_DOMAIN) + self._attr_options = options + self._attr_current_option = options[0] if len(options) > 0 else None + + +def _validate_step_sensor( hass: HomeAssistant, config: dict[str, Any], value: str | list[str] ) -> tuple[dict[str, str], PreviewSensorEntity | None]: """Validate the matches step.""" @@ -853,5 +995,5 @@ def _validate_step_matches( errors[CONF_STATE_CLASS] = str(ex.msg) if errors: return errors, None - preview: PreviewSensorEntity = PreviewSensorEntity(hass, config=config, value=value) + preview: PreviewSensorEntity = PreviewSensorEntity(value=value, config=config) return errors, preview diff --git a/custom_components/pdf_scrape/const.py b/custom_components/pdf_scrape/const.py index 3fd2150..7039f09 100644 --- a/custom_components/pdf_scrape/const.py +++ b/custom_components/pdf_scrape/const.py @@ -5,6 +5,8 @@ from re import Pattern from typing import Final +from homeassistant.config_entries import ConfigSubentry + CONF_DEFAULT_SCAN_INTERVAL: Final[timedelta] = timedelta(minutes=5) CONF_MIN_SCAN_INTERVAL: Final[timedelta] = timedelta(seconds=30) DOMAIN: Final[str] = "pdf_scrape" @@ -12,10 +14,11 @@ CONF_REGEX_SEARCH: Final[str] = "regex_search" CONF_REGEX_MATCH_INDEX: Final[str] = "regex_match_index" CONF_VALUE_TEMPLATE: Final[str] = "value_template" -CONF_MD5_CHECKSUM: Final = "md5_checksum" +CONF_SHA256_CHECKSUM: Final = "sha256_checksum" CONF_MODIFIED: Final[str] = "modified" CONF_MODIFIED_SOURCE: Final[str] = "modified_source" CONF_FILE: Final[str] = "file" +CONF_OCR: Final[str] = "ocr" class ErrorTypes(StrEnum): @@ -39,3 +42,8 @@ class ConfType(StrEnum): HTTP = "http" UPLOAD = "upload" LOCAL = "local" + + +DOCUMENT_SUBENTRY: ConfigSubentry = ConfigSubentry( + subentry_type="document", title="PDF", unique_id="document", data={} +) diff --git a/custom_components/pdf_scrape/coordinator.py b/custom_components/pdf_scrape/coordinator.py index a9039cf..dc19680 100644 --- a/custom_components/pdf_scrape/coordinator.py +++ b/custom_components/pdf_scrape/coordinator.py @@ -28,8 +28,8 @@ HTTPError, PDFParseError, PDFScrape, + PDFScrapeFile, PDFScrapeHTTP, - PDFScrapeLocal, PDFScrapeUpload, ) @@ -65,14 +65,15 @@ async def _async_update_data(self) -> dict[str, str]: """Perform the update.""" try: if not self.data or await self.pdf.update(): - for subentry_conf_key in self.config_entry.subentries: - subentry_conf: ConfigSubentry = self.config_entry.subentries[ - subentry_conf_key - ] + for subentry_key, subentry_conf in self.config_entry.subentries.items(): + if subentry_conf.subentry_type == "document": + continue txt: str = "" try: - txt = self.pdf.get_pages(subentry_conf.data[CONF_PDF_PAGES]) + txt = await self.pdf.get_pages( + subentry_conf.data[CONF_PDF_PAGES] + ) except IndexError as ex: async_raise_error( hass=self.hass, @@ -133,8 +134,9 @@ async def _async_update_data(self) -> dict[str, str]: exception=ex, config_subentry=subentry_conf, ) - self.data[subentry_conf_key] = txt + self.data[subentry_key] = txt except (HTTPError, PDFParseError) as ex: + # TODO: if http error do we retry? async_raise_error( hass=self.hass, error_key=ErrorTypes.PDF_ERROR, @@ -183,14 +185,14 @@ async def async_upload_pdf(self, pdf: PDFScrapeUpload) -> None: await self._async_update_data() -class PDFScrapeLocalCoordinator(PDFScrapeCoordinator): +class PDFScrapeFileCoordinator(PDFScrapeCoordinator): """Data coordinator to download and parse the files.""" def __init__( self, hass: HomeAssistant, config_entry: PDFScrapeConfigEntry, - pdf: PDFScrapeLocal, + pdf: PDFScrapeFile, ) -> None: """Initialize coordinator.""" super().__init__(hass, config_entry, pdf, CONF_MIN_SCAN_INTERVAL) diff --git a/custom_components/pdf_scrape/manifest.json b/custom_components/pdf_scrape/manifest.json index 6f93d2a..175065d 100644 --- a/custom_components/pdf_scrape/manifest.json +++ b/custom_components/pdf_scrape/manifest.json @@ -9,6 +9,6 @@ "integration_type": "service", "iot_class": "cloud_polling", "issue_tracker": "https://github.com/iluvdata/pdf_scrpae/issues", - "requirements": ["pypdf~=5.2.0"], - "version": "2025.12.0" + "requirements": ["pymupdf==1.27.2.3","pymupdf4llm==1.27.2.3","rapidocr==3.8.1","onnxruntime==1.25.1"], + "version": "2026.5.0" } diff --git a/custom_components/pdf_scrape/pdf.py b/custom_components/pdf_scrape/pdf.py index cba9e78..766113e 100644 --- a/custom_components/pdf_scrape/pdf.py +++ b/custom_components/pdf_scrape/pdf.py @@ -1,31 +1,32 @@ -"""PDFScrape API.""" +"""PDF Scrape File Handling.""" from abc import ABC, abstractmethod +from asyncio import Task, TaskGroup import datetime from enum import StrEnum from functools import partial -from hashlib import md5 -from io import BufferedReader, BytesIO +from hashlib import file_digest +from io import BytesIO +import logging from pathlib import Path -from typing import IO, Any, Final, cast - -from aiohttp import ( - ClientConnectorError, - ClientResponse, - ClientResponseError, - ClientSession, -) -from pypdf import DocumentInformation, PdfReader -from pypdf.errors import PyPdfError - -from homeassistant.components.hassio import async_get_clientsession +import re +from typing import Final + +from httpx import HTTPStatusError, RequestError, Response +from PIL import Image +from pydantic import BaseModel, Field +from pymupdf import Document, Pixmap, TextPage + from homeassistant.core import HomeAssistant -from homeassistant.helpers.storage import Store +from homeassistant.helpers.httpx_client import get_async_client +from homeassistant.helpers.storage import STORAGE_DIR, Store from .const import DOMAIN STORE_VERSION: Final[int] = 1 +_LOGGER = logging.getLogger(__name__) + class ModifiedDateSource(StrEnum): """Enum for how the date gets updated.""" @@ -38,14 +39,97 @@ class ModifiedDateSource(StrEnum): UPLOAD = "upload" -type StoredFile = dict[ - str, list[str] | datetime.datetime | ModifiedDateSource | str | None -] +class PDF(BaseModel): + """Class for the stored file in storage.""" + + modified: datetime.datetime | None = None + title: str | None = None + sha256_checksum: str | None = None + modified_source: ModifiedDateSource | None = None + page_count: int = 0 + pages: dict[int, PDFPage] = {} + http_headers: HTTPHeaders | None = None + loaded_from_store: bool = Field(exclude=True, default=False) + + +class HTTPHeaders(BaseModel): + """Class for HTTP headers (to avoid constantly fetching the entire pdf).""" + last_modified: datetime.datetime + content_length: int -def get_store(hass: HomeAssistant, key: str) -> Store[StoredFile]: + +class PDFPage(BaseModel): + """Class for a PDF Page.""" + + ocr: bool + text: str + + +def get_store(hass: HomeAssistant, key: str) -> Store[PDF]: """Get a store.""" - return Store[StoredFile](hass, STORE_VERSION, f"{DOMAIN}_{key}") + return Store[PDF](hass, STORE_VERSION, f"{DOMAIN}_{key}") + + +class Progress: + """Class to track progress of loading and processing the pdf.""" + + def __init__(self) -> None: + """Initialize progress.""" + self._progress_tasks: list[(float, float)] = [] + self._cur_task_index: int = 0 + + def define_tasks(self, tasks: list[float]) -> None: + """Add a progress task.""" + if 0 in tasks: + raise ValueError("task estimates must be > 0") + if not sum(tasks) == 1: + raise ValueError("task estimate must sum to 1") + if len(self._progress_tasks) == 0: + self._progress_tasks = [(task, 0) for task in tasks] + return + # Normalize the task estimates so they add up to 1 + normalized_tasks: list[float] = [ + task * self._progress_tasks[self._cur_task_index][0] for task in tasks + ] + old_tasks = self._progress_tasks.copy() + for i, pt in enumerate( + old_tasks[self._cur_task_index :], start=self._cur_task_index + ): + if i == self._cur_task_index: + for j, task in enumerate(normalized_tasks): + if i + j < len(self._progress_tasks): + self._progress_tasks[i + j] = (task, 0) + else: + self._progress_tasks.append((task, 0)) + elif i + len(tasks) < len(self._progress_tasks): + self._progress_tasks[i + len(tasks)] = pt + else: + self._progress_tasks.append(pt) + + def clear_tasks(self) -> None: + """Clear the task list.""" + self._progress_tasks = [] + self._cur_task_index = 0 + + @property + def progress(self) -> float: + """Get the current progress.""" + return sum([cur for _, cur in self._progress_tasks]) + + def advance_steps(self, tasks: int = 1) -> float: + """Notify progress listeners.""" + for i in range(self._cur_task_index, self._cur_task_index + tasks): + self._progress_tasks[i] = ( + self._progress_tasks[i][0], + self._progress_tasks[i][0], + ) + self._cur_task_index += tasks + update: float = self.progress + if update == 1: + self.clear_tasks() + _LOGGER.debug("Progress updated: %s", update) + return update class PDFScrape(ABC): @@ -54,104 +138,213 @@ class PDFScrape(ABC): def __init__(self, hass: HomeAssistant, config_entry_id: str | None) -> None: """Called by classmethod with is called by the subclass.""" self.hass: HomeAssistant = hass - self.pages: list[str] = [] - self.modified: datetime.datetime | None = None - self.modified_source: ModifiedDateSource | None = None - self.metadata_name: str | None = None - self.md5_checksum: str - self.stored_file: StoredFile | None = None + self._document: Document + self.pdf: PDF = PDF() self.config_entry_id: str | None = config_entry_id - # if config_entry_id is None that means this a config flow and so just sents the file - self.store: Store[StoredFile] | None = ( + self._stream: BytesIO + self._progress = Progress() + + # if config_entry_id is None that means this a config flow and so just sends the file + self.store: Store[PDF] | None = ( get_store(hass, self.config_entry_id) if self.config_entry_id is not None else None ) + @property + def progress(self) -> float: + """Get the progress in progress.""" + return self._progress.progress + async def _pdf_scrape(self): if self.store is not None: - self.stored_file = await self.store.async_load() - if not self.stored_file: - self.stored_file = {} + if stored_file := await self.store.async_load(): + self.pdf = PDF(**stored_file, loaded_from_store=True) await self.update() async def _process_pdf( self, - stream: IO[Any], alt_timestamp: tuple[datetime.datetime, ModifiedDateSource] | None = None, - upload: bool = False, ) -> bool: - """(Re)load a pdf from a url.""" - # return true is updated. - try: - pdfr: PdfReader = PdfReader(stream) - metadata: DocumentInformation | None = pdfr.metadata - if metadata: - self.modified = metadata.modification_date - self.modified_source = ModifiedDateSource.PDF_METADATA - if upload: - self.metadata_name = metadata.title - if self.modified is not None: - self.modified = self.modified.replace(tzinfo=datetime.UTC) - if self.modified is None and alt_timestamp is not None: - self.modified, self.modified_source = alt_timestamp - hash_md5 = md5() - for chunk in iter(lambda: stream.read(4096), b""): - hash_md5.update(chunk) - self.md5_checksum = hash_md5.hexdigest() - # Check if there are changes, otherwise we should stop to save comp time - if ( - self.stored_file - and self.modified - == datetime.datetime.fromisoformat(self.stored_file.get("modified")) - and self.md5_checksum == self.stored_file.get("md5_checksum") - ): - pdfr.close() - if isinstance(stream, BytesIO): - stream.close() - return False - self.pages = [page.extract_text() for page in pdfr.pages] - pdfr.close() - if isinstance(stream, BytesIO): - stream.close() - except PyPdfError as err: - raise PDFParseError from err - if self.store is not None: - if self.stored_file is None: - self.stored_file = {} - self.stored_file["modified"] = self.modified.isoformat() - self.stored_file["md5_checksum"] = self.md5_checksum - self.stored_file["modified_source"] = self.modified_source - self.stored_file["pages"] = self.pages - await self.store.async_save(self.stored_file) - return True - - async def _load_from_storage(self) -> None: - if self.store is not None: - self.stored_file = await self.store.async_load() - if self.stored_file is not None: - self.pages = cast(list[str], self.stored_file.get("pages")) - self.modified = datetime.datetime.fromisoformat( - self.stored_file.get("modified") + """(Re)load a pdf from a url. + + returns true if the pdf was updated (either modified date or checksum), false if not. + """ + _LOGGER.debug("Start processing PDF") + tasks: list[float] = [0.05, 0.05, 0.65, 0.25] + self._progress.define_tasks(tasks) + self._document = await self.hass.async_add_executor_job( + partial(Document, stream=self._stream) + ) + self._progress.advance_steps() + modified: datetime.datetime | None = None + title: str | None = None + if self._document.metadata: + if "title" in self._document.metadata: + title = self._document.metadata["title"] + if "modDate" in self._document.metadata: + matches: re.Match[str] | None = re.search( + r"(\d{14}-\d{2})(?:')(\d{2})(?:')", + self._document.metadata["modDate"], ) - self.modified_source = cast( - ModifiedDateSource, self.stored_file.get("modified_source") + if matches: + modified = datetime.datetime.strptime( + f"{matches.group(1)}{matches.group(2)}", "%Y%m%d%H%M%S%z" + ) + self.pdf.modified_source = ModifiedDateSource.PDF_METADATA + modified.replace(tzinfo=datetime.UTC) + if modified is None and alt_timestamp is not None: + modified, self.pdf.modified_source = alt_timestamp + self._stream.seek(0) # reset pointer + digest_sha256 = await self.hass.async_add_executor_job( + file_digest, self._stream, "sha256" + ) + sha256_checksum: str = digest_sha256.hexdigest() + self._progress.advance_steps() + # Check if there are changes, otherwise we should stop to save comp time + if ( + self.pdf.loaded_from_store + and modified == self.pdf.modified + and sha256_checksum == self.pdf.sha256_checksum + ): + await self.close() + self._progress.advance_steps(2) + _LOGGER.debug("PDF not modified since last load, skipping processing") + return False + self.pdf.modified = modified + self.pdf.sha256_checksum = sha256_checksum + self.pdf.title = title + self.pdf.page_count = self._document.page_count + if self.store is not None: + if len(self.pdf.pages) > 0: + # already loaded pages, do we need to re-ocr them? + await self._get_pages(set(self.pdf.pdf.pages.keys()), update=True) + await self.store.async_save(self.pdf.model_dump()) + # Generate a thumbnail + pixmap: Pixmap = await self.hass.async_add_executor_job( + self._document[0].get_pixmap + ) + # Resize to 512x512 maintining aspect ratio + pil_image: Image.Image = pixmap.pil_image() + await self.hass.async_add_executor_job( + pil_image.thumbnail, (512, 512), Image.Resampling.BICUBIC + ) + pdf_storage_path: Path = Path( + self.hass.config.path( + STORAGE_DIR, + DOMAIN, ) - self.md5_checksum = cast(str, self.stored_file["md5_checksum"]) - return - raise StoredFileError + ) + if not pdf_storage_path.exists(): + await self.hass.async_add_executor_job(pdf_storage_path.mkdir) + await self.hass.async_add_executor_job( + pil_image.save, + f"{pdf_storage_path}/{self.config_entry_id}.webp", + "WEBP", + ) + self._progress.advance_steps() + # save the actual pdf file (if neeeded) + if isinstance(self, (PDFScrapeHTTP, PDFScrapeUpload)): + self._stream.seek(0) + path: Path = Path(f"{pdf_storage_path}/{self.config_entry_id}.pdf") + with await self.hass.async_add_executor_job( + partial( + path.open, + mode="wb", + ) + ) as f: + memview = self._stream.getbuffer() + await self.hass.async_add_executor_job(f.write, memview) + memview.release() + await self.close() + _LOGGER.debug("PDF Finished Processing") + return True @abstractmethod async def update(self) -> bool: """Must be implemented by sub_classes.""" - def close(self) -> None: - """Close to free up memory occupied by the pdf txt.""" - self.pages = [] + async def close(self) -> None: + """Close to free up memory occupied by the pdf and file lock.""" + if hasattr(self, "_document") and not self._document.is_closed: + await self.hass.async_add_executor_job(self._document.close) + if hasattr(self, "_stream") and not self._stream.closed: + self._stream.close() - def get_pages(self, page_range: str) -> str: - """Parse page range string into list of page numbers.""" + async def _get_pages( + self, + page_nums: set[int], + ocr: bool = False, + update: bool = False, + ) -> int: + """Get txt on a pages.""" + progress_value: float = 1 / len(page_nums) + self._progress.define_tasks(tasks=[progress_value] * len(page_nums)) + tasks: dict[int, Task] = {} + async with TaskGroup() as tg: + for page in page_nums: + page_index = page - 1 + if page_index not in self.pdf.pages or ( + ocr and not self.pdf.pages[page_index].ocr + ): + tasks[page_index] = tg.create_task( + self._get_page_text(page_index, ocr) + ) + elif update: + tasks[page_index] = tg.create_task( + self._get_page_text(page_index, self.pdf.pages[page_index].ocr) + ) + for page_index, task in tasks.items(): + if task.exception(): + _LOGGER.exception( + "Error processing page %s", + page_index + 1, + exc_info=task.exception(), + ) + self.pdf.pages[page_index] = PDFPage( + ocr=ocr or (update and self.pdf.pages[page_index].ocr), + text=task.result(), + ) + + async def _load_stream_from_file(self, file: Path) -> None: + """Load the file into a stream.""" + with await self.hass.async_add_executor_job(partial(file.open, mode="rb")) as f: + self._stream = BytesIO(await self.hass.async_add_executor_job(f.read)) + + async def _load_document_from_file_or_cache(self) -> None: + """Load the document from file or cache.""" + if ( + hasattr(self, "_document") + and self._document is not None + and not self._document.is_closed + ): + return + if hasattr(self, "file"): + await self._load_stream_from_file(self.file) + else: + await self._load_stream_from_file( + Path( + self.hass.config.path( + STORAGE_DIR, DOMAIN, f"{self.config_entry_id}.pdf" + ) + ) + ) + self._document = await self.hass.async_add_executor_job( + partial(Document, stream=self._stream) + ) + + async def _get_page_text(self, page_index: int, ocr: bool = False) -> str: + """Get text from a specific page.""" + await self._load_document_from_file_or_cache() + text_page: TextPage = await self.hass.async_add_executor_job( + self._document[page_index].get_textpage + if not ocr + else self._document[page_index].get_textpage_ocr + ) + return await self.hass.async_add_executor_job(text_page.extractText) + async def get_pages(self, page_range: str, ocr: bool = False) -> str: + """Parse page range string into list of page numbers.""" page_nums: set[int] = set() for part in page_range.split(","): if "-" in part: @@ -160,19 +353,23 @@ def get_pages(self, page_range: str) -> str: page_nums.update(range(start, end + 1)) else: page_nums.add(int(part)) - if max(page_nums) > len(self.pages) or min(page_nums) < 1: + if max(page_nums) > self.pdf.page_count or min(page_nums) < 1: raise IndexError("Page number out of range") - return "\n".join(self.pages[page - 1] for page in sorted(page_nums)) + await self._get_pages(page_nums, ocr) + return "\n".join( + self.pdf.pages[page - 1].text or "" for page in sorted(page_nums) + ) class PDFScrapeHTTP(PDFScrape): """Parse pdf from http/https source.""" - def __init__(self, hass: HomeAssistant, config_entry_id: str | None) -> None: - """Call only from classmethod.""" + def __init__( + self, hass: HomeAssistant, url: str, config_entry_id: str | None = None + ) -> None: + """Call from class method unless need to monitor progress on first load.""" super().__init__(hass, config_entry_id) - self.url: str - self.session: ClientSession + self.url: str = url @classmethod async def pdfscrape( @@ -183,9 +380,7 @@ async def pdfscrape( config_entry_id: str | None = None, ): """Instantiate a pdfscrape class.""" - self = cls(hass, config_entry_id) - self.url = url - self.session = async_get_clientsession(self.hass) + self = cls(hass, url, config_entry_id) await self._pdf_scrape() return self @@ -196,128 +391,171 @@ def __repr__(self) -> str: async def update(self) -> bool: """(Re)load a pdf from a URL.""" try: - resp: ClientResponse = await self.session.get(self.url) - stream: BytesIO = BytesIO(await resp.read()) - alt_modified: datetime - alt_modified_source: ModifiedDateSource - if resp.headers.get("late-modified"): - alt_modified = datetime.strptime( - resp.headers["last-modified"], "%a, %d %b %Y %H:%M:%S %Z" - ) - alt_modified_source = ModifiedDateSource.HTTP_HEADER - else: - alt_modified = datetime.datetime.now(datetime.UTC) - alt_modified_source = ModifiedDateSource.FIRST_CHECK - if await self._process_pdf( - stream, - (alt_modified, alt_modified_source), + if self.pdf.http_headers is not None: + async with get_async_client(self.hass) as client: + r: Response = await client.head(self.url) + if "last-modified" in r.headers and "content-length" in r.headers: + new_headers = HTTPHeaders( + last_modified=convert_header_date( + r.headers["last-modified"] + ), + content_length=int(r.headers["content-length"]), + ) + + if new_headers == self.pdf.http_headers: + _LOGGER.debug( + "HTTP headers indicate PDF has not changed, skipping download" + ) + return False + self._progress.clear_tasks() + self._progress.define_tasks([0.2, 0.8]) + async with ( + get_async_client(self.hass) as client, + client.stream("GET", self.url) as r, ): - return True - await self._load_from_storage() - - except (ClientResponseError, ClientConnectorError) as err: + r.raise_for_status() + self._stream = BytesIO() + async for chunk in r.aiter_bytes(): + self._stream.write(chunk) + self.pdf.http_headers = HTTPHeaders( + last_modified=convert_header_date(r.headers["last-modified"]), + content_length=int(r.headers.get("content-length")), + ) + alt_modified: datetime + alt_modified_source: ModifiedDateSource + if self.pdf.http_headers.last_modified is not None: + alt_modified = self.pdf.http_headers.last_modified + alt_modified_source = ModifiedDateSource.HTTP_HEADER + else: + alt_modified = datetime.datetime.now(datetime.UTC) + alt_modified_source = ModifiedDateSource.FIRST_CHECK + self._progress.advance_steps() + return await self._process_pdf((alt_modified, alt_modified_source)) + except (RequestError, HTTPStatusError) as err: raise HTTPError(str(err)) from err - return False + +def convert_header_date(date_str: str) -> datetime.datetime: + """Convert HTTP header date to datetime.""" + return datetime.datetime.strptime(date_str, "%a, %d %b %Y %H:%M:%S %Z").replace( + tzinfo=datetime.UTC + ) class PDFScrapeFile(PDFScrape): """Parse pdf from file.""" def __init__( - self, hass: HomeAssistant, config_entry_id: str | None, path: Path | str | None + self, + hass: HomeAssistant, + config_entry_id: str | None, + file: Path | str, ) -> None: """Call only from classmethod.""" super().__init__(hass, config_entry_id) - self.path: Path | None = ( - path if isinstance(path, Path) or path is None else Path(path) - ) + self.file: Path = file if isinstance(file, Path) else Path(file) @classmethod async def pdfscrape( cls, hass: HomeAssistant, - path: Path | str | None, + file: Path | str, *, config_entry_id: str | None = None, ): """Initialize a PDFScrapeFile class.""" - self = cls(hass, config_entry_id, path) + self = cls(hass, config_entry_id, file) await self._pdf_scrape() return self - async def _update(self, upload: bool = False) -> bool: + async def update(self) -> bool: """Check for an update.""" - if self.path is not None: + if self.file is not None: try: - stream: BufferedReader = await self.hass.async_add_executor_job( - partial(self.path.open, mode="rb") + modified: datetime = datetime.datetime.fromtimestamp( + (await self.hass.async_add_job_executor(self.file.stat)).st_mtime, + datetime.UTC, ) - modified: datetime = ( - datetime.datetime.now(datetime.UTC) - if upload - else datetime.datetime.fromtimestamp( - self.path.stat().st_mtime, datetime.UTC + with await self.hass.async_add_executor_job( + partial(self.file.open, mode="rb") + ) as f: + self._stream = BytesIO( + await self.hass.async_add_executor_job(f.read) ) - ) if await self._process_pdf( - stream, ( modified, - ModifiedDateSource.UPLOAD - if upload - else ModifiedDateSource.FILE_MTIME, - ), - upload=upload, + ModifiedDateSource.FILE_MTIME, + ) ): return True except OSError as err: raise FileError(str(err)) from err - # We have an upload without an update, pull from file. - await self._load_from_storage() return False + def __repr__(self): + """Representation.""" + return f"PDF({self.file})" if self.file is not None else "PDF(Local File)" + -class PDFScrapeUpload(PDFScrapeFile): +class PDFScrapeUpload(PDFScrape): """Upload PDF Scape.""" + def __init__( + self, hass: HomeAssistant, config_entry_id: str, file: Path | str | None = None + ) -> None: + """Initialize for cached files only.""" + super().__init__(hass, config_entry_id) + if isinstance(file, str): + file = Path(file) + with file.open(mode="rb") as pdf_file: + self._stream = BytesIO() + self._stream.write(pdf_file.read) + @classmethod - async def pdfscrape( + async def async_from_file( cls, hass: HomeAssistant, - *, - path: Path | None = None, - config_entry_id: str | None = None, + file: Path | str, + config_entry_id: str, + ): + """Initialize a PDFScrapeUpload class but do not process.""" + self = cls(hass, config_entry_id) + if isinstance(file, str): + file = Path(file) + with await self.hass.async_add_executor_job( + partial(file.open, mode="rb") + ) as pdf_file: + self._stream = BytesIO() + self._stream.write(await self.hass.async_add_executor_job(pdf_file.read)) + return self + + @classmethod + async def pdfscrape( + cls, hass: HomeAssistant, config_entry_id: str, file: Path | str | None = None ): """Initialize a PDFScrapeUpload class.""" - if path is None and config_entry_id is None: - raise ValueError("Either path or config_entry_id must be specified") - self = cls(hass, config_entry_id, path) + if file is None: + self = cls(hass, config_entry_id) + else: + self = await cls.from_file(hass, file, config_entry_id) await self._pdf_scrape() return self - def __repr__(self): - """Representation.""" - return "PDF(Uploaded)" - async def update(self) -> bool: - """(Re)load a pdf from an upload.""" - return await self._update(upload=True) - - -class PDFScrapeLocal(PDFScrapeFile): - """Upload PDF Scape.""" + """Check for an update.""" + if hasattr(self, "_stream"): + return await self._process_pdf( + (datetime.datetime.now(datetime.UTC), ModifiedDateSource.UPLOAD) + ) + return False def __repr__(self): """Representation.""" - return f"PDF({self.path})" - - async def update(self) -> bool: - """(Re)load a pdf from an upload.""" - return await self._update() + return f"PDF Uploaded - {self.pdf.title}" if self.pdf.title else "PDF Uploaded" -class PDFParseError(PyPdfError): +class PDFParseError(Exception): """Unable to parse pdf.""" diff --git a/custom_components/pdf_scrape/repairs.py b/custom_components/pdf_scrape/repairs.py index d5abaa4..4a20022 100644 --- a/custom_components/pdf_scrape/repairs.py +++ b/custom_components/pdf_scrape/repairs.py @@ -5,12 +5,11 @@ import voluptuous as vol from homeassistant import data_entry_flow -from homeassistant.components.repairs import RepairsFlow +from homeassistant.components.repairs import FlowType, RepairsFlow, RepairsFlowResult from homeassistant.config_entries import ( SOURCE_RECONFIGURE, ConfigFlowContext, ConfigFlowResult, - FlowType, SubentryFlowContext, SubentryFlowResult, ) @@ -24,13 +23,13 @@ class PDFScrapeRepairFlow(RepairsFlow): async def async_step_init( self, user_input: dict[str, str] | None = None - ) -> data_entry_flow.FlowResult: + ) -> RepairsFlowResult: """Start reconfigure flow.""" return await self.async_step_confirm() async def async_step_confirm( self, user_input: dict[str, str] | None = None - ) -> data_entry_flow.FlowResult: + ) -> RepairsFlowResult: """Start reconfigure flow.""" if user_input is not None: return await self._async_get_next_flow() @@ -48,35 +47,35 @@ async def _async_get_next_flow(self) -> data_entry_flow.FlowResult: class PDFRepairFlow(PDFScrapeRepairFlow): """Repair for PDF errors.""" - async def _async_get_next_flow(self) -> ConfigFlowResult: + async def _async_get_next_flow(self) -> RepairsFlowResult: next_flow: ConfigFlowResult = await self.hass.config_entries.flow.async_init( DOMAIN, context=ConfigFlowContext( entry_id=self.data["entry_id"], source=SOURCE_RECONFIGURE ), ) - return self.async_create_entry( - data={}, next_flow=(FlowType.CONFIG_FLOW, next_flow["flow_id"]) + return self.async_abort( + next_flow=(FlowType.CONFIG_FLOW, next_flow["flow_id"]), + reason="pdf_error_reconfigure", ) class TargetRepairFlow(PDFScrapeRepairFlow): """Repair for Target Errors.""" - async def _async_get_next_flow(self) -> SubentryFlowResult: + async def _async_get_next_flow(self) -> RepairsFlowResult: next_flow: SubentryFlowResult = ( await self.hass.config_entries.subentries.async_init( (self.data["entry_id"], "target"), context=SubentryFlowContext( - entry_id=self.data["entry_id"], subentry_id=self.data["subentry_id"], source=SOURCE_RECONFIGURE, ), ) ) - return self.async_create_entry( - data={}, + return self.async_abort( next_flow=(FlowType.CONFIG_SUBENTRIES_FLOW, next_flow["flow_id"]), + reason="target_error_reconfigure", ) diff --git a/custom_components/pdf_scrape/sensor.py b/custom_components/pdf_scrape/sensor.py index 8ff52c3..cc92c59 100644 --- a/custom_components/pdf_scrape/sensor.py +++ b/custom_components/pdf_scrape/sensor.py @@ -17,14 +17,20 @@ EntityCategory, ) from homeassistant.core import HomeAssistant, callback -from homeassistant.exceptions import ConfigEntryError, HomeAssistantError +from homeassistant.exceptions import ConfigEntryError from homeassistant.helpers.device_registry import DeviceEntryType from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from homeassistant.helpers.update_coordinator import CoordinatorEntity from . import PDFScrapeConfigEntry -from .const import CONF_FILE, CONF_MD5_CHECKSUM, CONF_MODIFIED_SOURCE, DOMAIN, ConfType +from .const import ( + CONF_FILE, + CONF_MODIFIED_SOURCE, + CONF_SHA256_CHECKSUM, + DOMAIN, + ConfType, +) from .coordinator import PDFScrapeCoordinator @@ -36,10 +42,16 @@ async def async_setup_entry( """Set up PDFScrape Entity from a subconfig entry.""" coordinator: PDFScrapeCoordinator = config_entry.runtime_data - async_add_entities([PDFDocumentSensor(coordinator)]) - - for subentry_config_key in coordinator.data: - async_add_entities([PDFScrapeSensor(coordinator, subentry_config_key)]) + for subentry_id, subentry in config_entry.subentries.items(): + if subentry.subentry_type == "document": + async_add_entities( + [PDFDocumentSensor(coordinator)], config_subentry_id=subentry_id + ) + continue + async_add_entities( + [PDFScrapeSensor(coordinator, subentry)], + config_subentry_id=subentry_id, + ) def _async_get_device_info(config_entry: PDFScrapeConfigEntry) -> DeviceInfo: @@ -65,9 +77,9 @@ class PDFDocumentSensor(CoordinatorEntity[PDFScrapeCoordinator], SensorEntity): def __init__(self, coordinator: PDFScrapeCoordinator) -> None: """Initialize PDFDocument Sensor.""" super().__init__(coordinator) - self._attr_name = f"{self.coordinator.config_entry.title} Last Modified" + self._attr_name = "Last Modified" self._attr_device_class = SensorDeviceClass.TIMESTAMP - self.unique_id = f"{DOMAIN}_{self.coordinator.config_entry.entry_id}" + self.unique_id = f"{DOMAIN}_document_{self.coordinator.config_entry.entry_id}" self._attr_has_entity_name = True self._attr_device_info = _async_get_device_info(coordinator.config_entry) self._attr_icon = "mdi:update" @@ -82,14 +94,14 @@ def _handle_coordinator_update(self) -> None: @cached_property def native_value(self) -> datetime | None: """Return the state of the sensor.""" - return self.coordinator.pdf.modified + return self.coordinator.pdf.pdf.modified @cached_property def extra_state_attributes(self) -> dict[str, str]: """Return Extra Attributes.""" return { - CONF_MODIFIED_SOURCE: self.coordinator.pdf.modified_source, - CONF_MD5_CHECKSUM: self.coordinator.pdf.md5_checksum, + CONF_MODIFIED_SOURCE: self.coordinator.pdf.pdf.modified_source, + CONF_SHA256_CHECKSUM: self.coordinator.pdf.pdf.sha256_checksum, } @@ -97,30 +109,23 @@ class PDFScrapeSensor(CoordinatorEntity[PDFScrapeCoordinator], SensorEntity): # """PDFScrape Sensor Entity.""" def __init__( - self, coordinator: PDFScrapeCoordinator, subentry_config_key: str + self, coordinator: PDFScrapeCoordinator, subentry: ConfigSubentry ) -> None: """Initialize PDFScrape Sensor.""" super().__init__(coordinator) if coordinator.config_entry is None: raise ConfigEntryError("This should never be raised") - self.subentry_config: ConfigSubentry = coordinator.config_entry.subentries[ - subentry_config_key - ] - if self.subentry_config is None: - raise HomeAssistantError( - f"Subentry config not found: {subentry_config_key}" - ) - self.subentry_config_key = subentry_config_key - self._attr_name = self.subentry_config.title + self.subentry_id: str = subentry.subentry_id + self._attr_name = subentry.title self._attr_has_entity_name = True self._attr_device_info = _async_get_device_info(coordinator.config_entry) - self._attr_native_unit_of_measurement = self.subentry_config.data.get( + self._attr_native_unit_of_measurement = subentry.data.get( CONF_UNIT_OF_MEASUREMENT ) - self._attr_state_class = self.subentry_config.data.get(CONF_STATE_CLASS) - self._attr_device_class = self.subentry_config.data.get(CONF_DEVICE_CLASS) + self._attr_state_class = subentry.data.get(CONF_STATE_CLASS) + self._attr_device_class = subentry.data.get(CONF_DEVICE_CLASS) self._attr_icon = "mdi:file-pdf-box" - self.unique_id = f"{DOMAIN}_{subentry_config_key}" + self.unique_id = f"{DOMAIN}_target_{self.subentry_id}" @callback def _handle_coordinator_update(self) -> None: @@ -130,5 +135,5 @@ def _handle_coordinator_update(self) -> None: @cached_property def native_value(self) -> str: """Return the state of the sensor.""" - value: str = self.coordinator.data[self.subentry_config_key] + value: str = self.coordinator.data[self.subentry_id] return value if len(value) < 255 else value[:242] + " " diff --git a/custom_components/pdf_scrape/translations/en.json b/custom_components/pdf_scrape/translations/en.json index c114bb1..1e6e950 100644 --- a/custom_components/pdf_scrape/translations/en.json +++ b/custom_components/pdf_scrape/translations/en.json @@ -18,7 +18,7 @@ "scan_interval": "Update Interval" }, "data_description": { - "name": "If name not provided, the URL will be used as name", + "name": "If name not provided, will attempt to assign the name from the PDF metadata or URL will be used as name", "url": "URL (http:// or https:// only)", "scan_interval": "Minimum is {min_int}" } @@ -49,15 +49,26 @@ }, "error": { "invalid_url": "Bad URL", - "pdf_parse": "Cannot parse PDF", - "http_error": "Cannot access PDF @ provided URL", + "http_error": "Cannot access PDF @ provided URL: {msg}", "invalid_source": "Accessed configuration from an invalid flow", "unknown": "Unknown error", - "file_error": "File access error: {file}" + "file_error": "File access error: {msg}", + "pdf_parse": "Cannot parse PDF: {msg}", + "exception": "Error: {msg}" + }, + "progress": { + "pdf_process": "Processing PDF ..." }, "abort": { "already_configured": "PDF is already configured", - "reconfigure_successful": "PDF Reconfiguration successful." + "http_already_configured": "A PDF @ {url} is already configured", + "upload_already_configured": "A PDF with the same sha256 checksum is already uploaded. While there is an exceedingly small chance that 2 different pdf files will have the same checksum it's very unlikely. If you are certain that they pdf files are different, alter the metadata of the pdf file you are uploading which will create a unique checksum.", + "file_already_configured": "A PDF @ {file} is already configured", + "reconfigure_successful": "PDF Reconfiguration successful.", + "pdf_parse": "[%key:component::pdf_scrape::config::error::pdf_parse%]", + "exception": "[%key:component::pdf_scrape::config::error::exception%]", + "http_error": "[%key:component::pdf_scrape::config::error::http_error%]", + "file_error": "[%key:component::pdf_scrape::config::error::file_error%]" } }, "config_subentries": { @@ -68,16 +79,18 @@ "entry_type": "Scrape Target", "step": { "user": { - "title": "Target Page", + "title": "Target Page(s)", "description": "{title}", "data": { - "pdf_pages": "Pages" + "pdf_pages": "Pages", + "ocr": "Use OCR (use with caution)" }, "data_description": { - "pdf_pages": "Pages in PDF: {pages}. Use comma to separate multiple pages or hyphen for page ranges (e.g., 1,3-5,7)." + "pdf_pages": "Pages in PDF: {pages}. Use comma to separate multiple pages or hyphen for page ranges (e.g., 1,3-5,7).", + "ocr": "Use OCR to extract text. This can be very slow and resource intensive, particularly for a large number of pages. Use only if the PDF contains images and text extraction is not working. OCR results can be highly variable and may not produce usable results depending on the quality of the source PDF. Currently only English documents are supported. When possible, consider using an OCR tool prior to configuring the PDF in Home Assistant. \n \n This is disabled until tesseract is available." } }, - "regex": { + "select": { "title": "Regular Expression", "description": "Pages {pdf_pages}: {title}", "data": { @@ -88,12 +101,12 @@ "regex_search": "Leave blank to use all text on selected page" } }, - "matches": { + "sensor": { "title": "Configure Sensor", "data": { "name": "Name", "regex_match_index": "Select match", - "value_template": "Template", + "value_template": "Limited Template", "unit_of_measurement": "Unit of Measurement", "device_class": "Device Class", "state_class": "State Class", @@ -247,6 +260,28 @@ } }, "issues":{ + "test_issue": { + "title": "Test Issue", + "fix_flow": { + "step": { + "confirm": { + "title": "Test Issue", + "description": "{msg} \n \nReconfigure PDF?" + } + } + } + }, + "test_issue_a": { + "title": "Test Issue A", + "fix_flow": { + "step": { + "confirm": { + "title": "Test Issue A", + "description": "{msg} \n \nReconfigure PDF?" + } + } + } + }, "pdf_error": { "title": "Error Opening PDF ({conf})", "fix_flow": { diff --git a/hacs.json b/hacs.json index 1d6aa83..1d6e6ca 100644 --- a/hacs.json +++ b/hacs.json @@ -1,4 +1,4 @@ { "name": "PDF Scrape", - "homeassistant": "2025.7.2" + "homeassistant": "2026.6.0" } diff --git a/logo.svg b/logo.svg deleted file mode 100644 index 80199f6..0000000 --- a/logo.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Layer 1 - - - - - - - {{scrape}} - - From 8122c8a452a27d56d51ec9c29aea77a4dead8a0b Mon Sep 17 00:00:00 2001 From: Grant Ellsworth Date: Thu, 21 May 2026 14:00:21 -0400 Subject: [PATCH 3/6] interim commit --- custom_components/pdf_scrape/__init__.py | 6 +- custom_components/pdf_scrape/config_flow.py | 39 ++--- custom_components/pdf_scrape/const.py | 2 +- custom_components/pdf_scrape/coordinator.py | 16 +- custom_components/pdf_scrape/http.py | 78 +++++++++ custom_components/pdf_scrape/image.py | 82 +++++++++ custom_components/pdf_scrape/pdf.py | 33 ++-- .../pdf_scrape/quality_scale.yaml | 64 ++++++++ custom_components/pdf_scrape/sensor.py | 9 +- .../pdf_scrape/translations/en.json | 9 +- tests/__init__.py | 1 + tests/conftest.py | 1 + tests/sample.pdf | Bin 0 -> 48722 bytes tests/test_config_flow.py | 155 ++++++++++++++++++ 14 files changed, 447 insertions(+), 48 deletions(-) create mode 100644 custom_components/pdf_scrape/http.py create mode 100644 custom_components/pdf_scrape/image.py create mode 100644 custom_components/pdf_scrape/quality_scale.yaml create mode 100644 tests/__init__.py create mode 100644 tests/conftest.py create mode 100644 tests/sample.pdf create mode 100644 tests/test_config_flow.py diff --git a/custom_components/pdf_scrape/__init__.py b/custom_components/pdf_scrape/__init__.py index 982e32c..0159565 100644 --- a/custom_components/pdf_scrape/__init__.py +++ b/custom_components/pdf_scrape/__init__.py @@ -49,6 +49,7 @@ PDFScrapeUploadCoordinator, async_raise_error, ) +from .http import PDFView from .pdf import ( PDF, FileError, @@ -60,7 +61,7 @@ get_store, ) -_PLATFORMS: list[Platform] = [Platform.SENSOR] +_PLATFORMS: list[Platform] = [Platform.IMAGE, Platform.SENSOR] _LOGGER = logging.getLogger(__name__) @@ -189,6 +190,8 @@ def _one_of(data: dict[str, Any]) -> dict[str, Any]: ) tg.create_task(async_run_in_loop(hass, file.unlink)) + hass.http.register_view(PDFView(hass)) + return True @@ -286,7 +289,6 @@ async def async_remove_config_entry_device( hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.DeviceEntry ) -> bool: """Handle pre-device delete checks.""" - # TODO: Tesseract device: Also delete config_entry async def update_listener(hass: HomeAssistant, config_entry: ConfigEntry): diff --git a/custom_components/pdf_scrape/config_flow.py b/custom_components/pdf_scrape/config_flow.py index 43519e3..dfd8a4b 100644 --- a/custom_components/pdf_scrape/config_flow.py +++ b/custom_components/pdf_scrape/config_flow.py @@ -55,7 +55,6 @@ import homeassistant.helpers.issue_registry as ir from homeassistant.helpers.selector import ( BooleanSelector, - BooleanSelectorConfig, DurationSelector, DurationSelectorConfig, FileSelector, @@ -108,7 +107,7 @@ class PDFScrapeConfigFlow(ConfigFlow, domain=DOMAIN): MINOR_VERSION: int = 2 data: dict[str, str | timedelta | None] = {} - placeholders: dict[str, str] | None = None + placeholders: dict[str, str] | None = {} reason: str = "already_configured" pdf: PDFScrape title_fun: Callable[[], str] | None = None @@ -133,7 +132,7 @@ async def async_step_user( async def async_step_finish( self, user_input: dict[str, Any] | None = None - ) -> ConfigFlowResult | None: + ) -> ConfigFlowResult: """Finish this flow.""" await self.async_set_unique_id(self.unique_fun()) if entry := self.hass.config_entries.async_entry_for_domain_unique_id( @@ -476,7 +475,7 @@ async def async_step_user( self._progress_task = self.get_config_entry().async_create_task( self.hass, self.pdf.get_pages( - user_input[CONF_PDF_PAGES], user_input.get(CONF_OCR, False) + user_input[CONF_PDF_PAGES], bool(user_input.get(CONF_OCR, False)) ), "step_user_get_pages", True, @@ -491,7 +490,7 @@ async def async_step_user( self._progress_task = None else: self._progress_task = None - return self.async_show_progress_done(next_step_id="select") + return self.async_show_progress_done(next_step_id="regex") else: return self.async_show_progress( step_id="user", @@ -513,11 +512,7 @@ async def async_step_user( vol.Required(CONF_PDF_PAGES, default=default_pages): TextSelector( TextSelectorConfig(type=TextSelectorType.TEXT) ), - vol.Optional(CONF_OCR, default=ocr): BooleanSelector( - BooleanSelectorConfig( - read_only=True # until we figure out tesseract app. - ) - ), + vol.Optional(CONF_OCR, default=ocr): BooleanSelector(), } ), description_placeholders={ @@ -534,12 +529,14 @@ async def async_setup_preview(hass: HomeAssistant) -> None: """Set up preview WS API.""" websocket_api.async_register_command(hass, ws_start_preview) - async def async_step_select( + async def async_step_regex( self, user_input: dict[str, Any] | None = None ) -> SubentryFlowResult: """Get the regex.""" errors: dict[str, str] = {} - text: str = await self.pdf.get_pages(self.data[CONF_PDF_PAGES]) + text: str = await self.pdf.get_pages( + self.data[CONF_PDF_PAGES], self.data[CONF_OCR] + ) if user_input and CONF_REGEX_SEARCH in user_input: # Validate that it's a valid regex @@ -574,7 +571,7 @@ async def async_step_select( schema, self._get_reconfigure_subentry().data ) return self.async_show_form( - step_id="select", + step_id="regex", data_schema=schema, description_placeholders={ "title": self._get_entry().title, @@ -731,7 +728,7 @@ def async_remove(self) -> None: { vol.Required("type"): "target/start_preview", vol.Required("flow_id"): str, - vol.Required("flow_type"): vol.Any("config_subentries_flow"), + vol.Required("flow_type"): vol.All("config_subentries_flow"), vol.Required("user_input"): dict, } ) @@ -742,10 +739,8 @@ async def ws_start_preview( msg: dict[str, Any], ) -> None: """Generate a preview.""" - # entity_registry_entry: er.RegistryEntry | None = None - if msg["flow_type"] != "config_subentries_flow": - raise HomeAssistantError("invalid_flow") - # Get the config flow status + + # Get the config flow status flow_status: SubentryFlowResult = hass.config_entries.subentries.async_get( msg["flow_id"] ) @@ -756,7 +751,6 @@ async def ws_start_preview( ) if not config_entry: raise HomeAssistantError - # pdf: PDFScrape = config_entry.runtime_data.pdf errors: dict[str, str] = {} @@ -818,7 +812,7 @@ def async_preview_callback( else: pages = flow.data[CONF_PDF_PAGES] value = await pdf.get_pages(pages) - if step == "select": + if step == "regex": pattern: str | None = user_input.get(CONF_REGEX_SEARCH) if pattern: user_input[CONF_ICON] = "mdi:text-box-search-outline" @@ -939,12 +933,9 @@ def async_show_preview( class PreviewSensorEntity(PDFPreviewEntity, SensorEntity): """Preview sensor entity for frontend.""" - def __init__( - self, value: str, config: dict[str, Any], domain: str | None = None - ) -> None: + def __init__(self, value: str, config: dict[str, Any]) -> None: """Initialize a preview entity.""" super().__init__(config, SENSOR_DOMAIN) - self.domain: str | None = domain self._attr_device_class = config.get(CONF_DEVICE_CLASS) self._attr_native_unit_of_measurement = config.get(CONF_UNIT_OF_MEASUREMENT) self._attr_state_class = config.get(CONF_STATE_CLASS) diff --git a/custom_components/pdf_scrape/const.py b/custom_components/pdf_scrape/const.py index 7039f09..061fd5e 100644 --- a/custom_components/pdf_scrape/const.py +++ b/custom_components/pdf_scrape/const.py @@ -8,7 +8,7 @@ from homeassistant.config_entries import ConfigSubentry CONF_DEFAULT_SCAN_INTERVAL: Final[timedelta] = timedelta(minutes=5) -CONF_MIN_SCAN_INTERVAL: Final[timedelta] = timedelta(seconds=30) +CONF_MIN_SCAN_INTERVAL: Final[timedelta] = timedelta(minutes=1) DOMAIN: Final[str] = "pdf_scrape" CONF_PDF_PAGES: Final[str] = "pdf_pages" CONF_REGEX_SEARCH: Final[str] = "regex_search" diff --git a/custom_components/pdf_scrape/coordinator.py b/custom_components/pdf_scrape/coordinator.py index dc19680..73ebd93 100644 --- a/custom_components/pdf_scrape/coordinator.py +++ b/custom_components/pdf_scrape/coordinator.py @@ -2,6 +2,7 @@ from datetime import timedelta import logging +from random import SystemRandom import re from typing import Any @@ -12,7 +13,7 @@ import homeassistant.helpers.issue_registry as ir from homeassistant.helpers.template import Template, TemplateVarsType from homeassistant.helpers.translation import async_get_exception_message -from homeassistant.helpers.update_coordinator import DataUpdateCoordinator +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from .const import ( CONF_DEFAULT_SCAN_INTERVAL, @@ -60,6 +61,8 @@ def __init__( ) self.pdf: PDFScrape = pdf self.data = {} + self.http_error_count: int = 0 + self.access_token: str = hex(SystemRandom().getrandbits(256))[2:] async def _async_update_data(self) -> dict[str, str]: """Perform the update.""" @@ -136,13 +139,17 @@ async def _async_update_data(self) -> dict[str, str]: ) self.data[subentry_key] = txt except (HTTPError, PDFParseError) as ex: - # TODO: if http error do we retry? + if isinstance(ex, HTTPError) and self.http_error_count < 3: + self.http_error_count += 1 + raise UpdateFailed(retry_after=30) from ex async_raise_error( hass=self.hass, error_key=ErrorTypes.PDF_ERROR, config_entry=self.config_entry, exception=ex, + error_type=UpdateFailed, ) + self.http_error_count = 0 return self.data @@ -205,6 +212,7 @@ def async_raise_error( exception: Exception | None = None, translation_placeholders: dict[str, Any] | None = None, config_subentry: ConfigSubentry | None = None, + error_type: ConfigEntryError | UpdateFailed = ConfigEntryError, ) -> None: """Log issues, create repairs, and raise exceptions.""" @@ -239,12 +247,12 @@ def async_raise_error( translation_placeholders=translation_placeholders, ) if exception is not None: - raise ConfigEntryError( + raise error_type( translation_domain=DOMAIN, translation_key=error_key, translation_placeholders=translation_placeholders, ) from exception - raise ConfigEntryError( + raise error_type( translation_domain=DOMAIN, translation_key=error_key, translation_placeholders=translation_placeholders, diff --git a/custom_components/pdf_scrape/http.py b/custom_components/pdf_scrape/http.py new file mode 100644 index 0000000..b8c9252 --- /dev/null +++ b/custom_components/pdf_scrape/http.py @@ -0,0 +1,78 @@ +"""View to load local pdfs.""" + +import os + +from aiohttp import hdrs, web + +from homeassistant.components.http import HomeAssistantView +from homeassistant.core import HomeAssistant +from homeassistant.helpers.http import KEY_AUTHENTICATED +from homeassistant.helpers.storage import STORAGE_DIR + +from .const import DOMAIN, ConfType +from .coordinator import PDFScrapeConfigEntry + + +async def async_setup(hass: HomeAssistant) -> None: + """Set up the PDF view.""" + hass.http.register_view(PDFView(hass)) + + +class PDFView(HomeAssistantView): + """PDF View.""" + + name = "api:pdfscrape:pdf" + url = "/api/pdf_scrape/pdf/{entry_id}.pdf" + requires_auth = False + + def __init__(self, hass: HomeAssistant) -> None: + """Initialize a PDFView.""" + self.hass = hass + + async def head(self, request: web.Request, entry_id: str) -> web.Response: + """Head just for length and last-modified.""" + entry: PDFScrapeConfigEntry = self._get_entry_and_authenticatey( + request, entry_id + ) + path: str = self.hass.config.path(STORAGE_DIR, DOMAIN, f"{entry_id}.pdf") + try: + size: int = await self.hass.async_add_executor_job(os.path.getsize, path) + except FileNotFoundError as exc: + raise web.HTTPFound(reason="PDF is missing from file system") from exc + return web.Response( + content_type="application/pdf", + content_length=size, + last_modified=entry.runtime_data.pdf.pdf.modified, + ) + + async def get(self, request: web.Request, entry_id: str) -> web.FileResponse: + """Serve the pdf.""" + entry: PDFScrapeConfigEntry = self._get_entry_and_authenticate( + request, entry_id + ) + response: web.FileResponse = web.FileResponse( + self.hass.config.path(STORAGE_DIR, DOMAIN, f"{entry_id}.pdf") + ) + response.last_modified = entry.runtime_data.pdf.pdf.modified + return response + + def _get_entry_and_authenticate( + self, request: web.Request, entry_id: str + ) -> PDFScrapeConfigEntry: + if entry := self.hass.config_entries.async_get_entry(entry_id): + if entry.data["type"] == ConfType.HTTP: + raise web.HTTPBadRequest(reason="Can't request for HTTP/HTTPS pdfs") + authenticated = ( + request[KEY_AUTHENTICATED] + or request.query.get("token") == entry.runtime_data.access_token + ) + if not authenticated: + # Attempt with invalid bearer token, raise unauthorized + # so ban middleware can handle it. + if hdrs.AUTHORIZATION in request.headers: + raise web.HTTPUnauthorized + # Invalid sigAuth or image entity access token + raise web.HTTPForbidden + + return entry + raise web.HTTPNotFound(reason="PDF not found") diff --git a/custom_components/pdf_scrape/image.py b/custom_components/pdf_scrape/image.py new file mode 100644 index 0000000..063369a --- /dev/null +++ b/custom_components/pdf_scrape/image.py @@ -0,0 +1,82 @@ +"""Image entityfor PDFScape.""" + +from datetime import datetime +import logging +from pathlib import Path + +from homeassistant.components.image import ImageEntity +from homeassistant.const import EntityCategory +from homeassistant.core import HomeAssistant, callback +from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback +from homeassistant.helpers.storage import STORAGE_DIR +from homeassistant.helpers.update_coordinator import CoordinatorEntity + +from .const import DOMAIN +from .coordinator import PDFScrapeConfigEntry, PDFScrapeCoordinator +from .sensor import async_get_device_info + +_LOGGER: logging.Logger = logging.getLogger(__name__) + + +async def async_setup_entry( + hass: HomeAssistant, + config_entry: PDFScrapeConfigEntry, + async_add_entities: AddConfigEntryEntitiesCallback, +) -> None: + """Set up PDFScrape Entity from a subconfig entry.""" + document_subentry_id: str = [ + subentry.subentry_id + for subentry in config_entry.subentries.values() + if subentry.unique_id == "document" + ][0] + async_add_entities( + [PDFImageEntity(config_entry.runtime_data)], + config_subentry_id=document_subentry_id, + ) + + +class PDFImageEntity(ImageEntity, CoordinatorEntity[PDFScrapeCoordinator]): + """Image entity for PDFScrape.""" + + def __init__( + self, + coordinator: PDFScrapeCoordinator, + ) -> None: + """Initialize the sensor.""" + super().__init__(coordinator.hass) + super(ImageEntity, self).__init__(coordinator) + self.device_info = async_get_device_info(coordinator.config_entry) + self.hass = coordinator.hass + self.unique_id = f"{DOMAIN}_thumbnail_{self.coordinator.config_entry.entry_id}" + self._attr_name = "Thumbnail" + self.has_entity_name = True + self._attr_entity_category = EntityCategory.DIAGNOSTIC + + @property + def image_last_updated(self) -> datetime | None: + """Return the last updated time of the pdf.""" + return self.coordinator.pdf.pdf.modified + + def image(self) -> bytes | None: + """Return the image.""" + try: + with Path.open( + self.coordinator.hass.config.path( + STORAGE_DIR, + DOMAIN, + f"{self.coordinator.config_entry.entry_id}.webp", + ), + "rb", + ) as file: + return file.read() + except FileNotFoundError: + _LOGGER.error( + "Image file not found for entry %s", + self.coordinator.config_entry.entry_id, + ) + return None + + @callback + def _handle_coordinator_update(self) -> None: + """Handle updated data from the coordinator.""" + self.async_write_ha_state() diff --git a/custom_components/pdf_scrape/pdf.py b/custom_components/pdf_scrape/pdf.py index 766113e..70d2108 100644 --- a/custom_components/pdf_scrape/pdf.py +++ b/custom_components/pdf_scrape/pdf.py @@ -16,6 +16,7 @@ from PIL import Image from pydantic import BaseModel, Field from pymupdf import Document, Pixmap, TextPage +from pymupdf4llm import to_text from homeassistant.core import HomeAssistant from homeassistant.helpers.httpx_client import get_async_client @@ -285,7 +286,7 @@ async def _get_pages( for page in page_nums: page_index = page - 1 if page_index not in self.pdf.pages or ( - ocr and not self.pdf.pages[page_index].ocr + ocr != self.pdf.pages[page_index].ocr ): tasks[page_index] = tg.create_task( self._get_page_text(page_index, ocr) @@ -336,12 +337,21 @@ async def _load_document_from_file_or_cache(self) -> None: async def _get_page_text(self, page_index: int, ocr: bool = False) -> str: """Get text from a specific page.""" await self._load_document_from_file_or_cache() - text_page: TextPage = await self.hass.async_add_executor_job( - self._document[page_index].get_textpage - if not ocr - else self._document[page_index].get_textpage_ocr + if not ocr: + text_page: TextPage = await self.hass.async_add_executor_job( + self._document[page_index].get_textpage + ) + return await self.hass.async_add_executor_job(text_page.extractText) + return await self.hass.async_add_executor_job( + partial( + to_text, + self._document, + use_ocr=True, + header=True, + footer=True, + pages=[page_index], + ) ) - return await self.hass.async_add_executor_job(text_page.extractText) async def get_pages(self, page_range: str, ocr: bool = False) -> str: """Parse page range string into list of page numbers.""" @@ -506,11 +516,12 @@ def __init__( ) -> None: """Initialize for cached files only.""" super().__init__(hass, config_entry_id) - if isinstance(file, str): - file = Path(file) - with file.open(mode="rb") as pdf_file: - self._stream = BytesIO() - self._stream.write(pdf_file.read) + if file: + if isinstance(file, str): + file = Path(file) + with file.open(mode="rb") as pdf_file: + self._stream = BytesIO() + self._stream.write(pdf_file.read()) @classmethod async def async_from_file( diff --git a/custom_components/pdf_scrape/quality_scale.yaml b/custom_components/pdf_scrape/quality_scale.yaml new file mode 100644 index 0000000..4778c97 --- /dev/null +++ b/custom_components/pdf_scrape/quality_scale.yaml @@ -0,0 +1,64 @@ +rules: + # Bronze + action-setup: done + appropriate-polling: done + brands: done + common-modules: done + config-flow-test-coverage: todo + config-flow: done + dependency-transparency: todo + docs-actions: todo + docs-high-level-description: todo + docs-installation-instructions: todo + docs-removal-instructions: todo + entity-event-setup: todo + entity-unique-id: todo + has-entity-name: todo + runtime-data: todo + test-before-configure: todo + test-before-setup: todo + unique-config-entry: + status: done + comment: | + Using the api-key which maps 1:1 to an account and the devices/entities will all generate consistent unique IDs from the + device_id provided. Additionally the integration only allows for single entry (single_config_entry: true). + + # Silver + action-exceptions: todo + config-entry-unloading: todo + docs-configuration-parameters: todo + docs-installation-parameters: todo + entity-unavailable: todo + integration-owner: todo + log-when-unavailable: todo + parallel-updates: todo + reauthentication-flow: todo + test-coverage: todo + + # Gold + devices: todo + diagnostics: todo + discovery-update-info: todo + discovery: todo + docs-data-update: todo + docs-examples: todo + docs-known-limitations: todo + docs-supported-devices: todo + docs-supported-functions: todo + docs-troubleshooting: todo + docs-use-cases: todo + dynamic-devices: todo + entity-category: todo + entity-device-class: todo + entity-disabled-by-default: todo + entity-translations: todo + exception-translations: todo + icon-translations: todo + reconfiguration-flow: todo + repair-issues: todo + stale-devices: todo + + # Platinum + async-dependency: todo + inject-websession: done + strict-typing: todo \ No newline at end of file diff --git a/custom_components/pdf_scrape/sensor.py b/custom_components/pdf_scrape/sensor.py index cc92c59..4c1b641 100644 --- a/custom_components/pdf_scrape/sensor.py +++ b/custom_components/pdf_scrape/sensor.py @@ -21,6 +21,7 @@ from homeassistant.helpers.device_registry import DeviceEntryType from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback +from homeassistant.helpers.network import get_url from homeassistant.helpers.update_coordinator import CoordinatorEntity from . import PDFScrapeConfigEntry @@ -54,11 +55,13 @@ async def async_setup_entry( ) -def _async_get_device_info(config_entry: PDFScrapeConfigEntry) -> DeviceInfo: +def async_get_device_info(config_entry: PDFScrapeConfigEntry) -> DeviceInfo: + """Get device info for the PDFScrape integration.""" device_info: DeviceInfo = DeviceInfo( identifiers={(DOMAIN, config_entry.entry_id)}, name=config_entry.title, entry_type=DeviceEntryType.SERVICE, + configuration_url=f"{get_url(config_entry.runtime_data.hass)}/api/pdf_scrape/pdf/{config_entry.entry_id}.pdf?token={config_entry.runtime_data.access_token}", ) match config_entry.data[CONF_TYPE]: case ConfType.LOCAL: @@ -81,7 +84,7 @@ def __init__(self, coordinator: PDFScrapeCoordinator) -> None: self._attr_device_class = SensorDeviceClass.TIMESTAMP self.unique_id = f"{DOMAIN}_document_{self.coordinator.config_entry.entry_id}" self._attr_has_entity_name = True - self._attr_device_info = _async_get_device_info(coordinator.config_entry) + self._attr_device_info = async_get_device_info(coordinator.config_entry) self._attr_icon = "mdi:update" self._attr_entity_category = EntityCategory.DIAGNOSTIC self._attr_translation_key = "modified" @@ -118,7 +121,7 @@ def __init__( self.subentry_id: str = subentry.subentry_id self._attr_name = subentry.title self._attr_has_entity_name = True - self._attr_device_info = _async_get_device_info(coordinator.config_entry) + self._attr_device_info = async_get_device_info(coordinator.config_entry) self._attr_native_unit_of_measurement = subentry.data.get( CONF_UNIT_OF_MEASUREMENT ) diff --git a/custom_components/pdf_scrape/translations/en.json b/custom_components/pdf_scrape/translations/en.json index 1e6e950..4d89a22 100644 --- a/custom_components/pdf_scrape/translations/en.json +++ b/custom_components/pdf_scrape/translations/en.json @@ -72,11 +72,14 @@ } }, "config_subentries": { + "document": { + "entry_type": "PDF Document (do not delete)" + }, "target": { "initiate_flow": { "user": "Add Search Target" }, - "entry_type": "Scrape Target", + "entry_type": "Search Target", "step": { "user": { "title": "Target Page(s)", @@ -87,10 +90,10 @@ }, "data_description": { "pdf_pages": "Pages in PDF: {pages}. Use comma to separate multiple pages or hyphen for page ranges (e.g., 1,3-5,7).", - "ocr": "Use OCR to extract text. This can be very slow and resource intensive, particularly for a large number of pages. Use only if the PDF contains images and text extraction is not working. OCR results can be highly variable and may not produce usable results depending on the quality of the source PDF. Currently only English documents are supported. When possible, consider using an OCR tool prior to configuring the PDF in Home Assistant. \n \n This is disabled until tesseract is available." + "ocr": "Use OCR to extract text. This can be very slow and resource intensive, particularly for a large number of pages. Use only if the PDF contains images and text extraction is not working. OCR results can be highly variable and may not produce usable results depending on the quality of the source PDF. Currently only English documents are supported. When possible, consider using an OCR tool prior to configuring the PDF in Home Assistant." } }, - "select": { + "regex": { "title": "Regular Expression", "description": "Pages {pdf_pages}: {title}", "data": { diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..1772374 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +"""Test suite for PDF Scrape integration.""" diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..4fc5432 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1 @@ +"""Fixtures for PDF Scrape tests.""" diff --git a/tests/sample.pdf b/tests/sample.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a27ca26451fdbdafad3b4fad4d85ba5eb6abea0a GIT binary patch literal 48722 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 str: + """Temp dir for config.""" + return hass_tmp_config_dir + + +async def test_user_flow_upload( + hass: HomeAssistant, + hass_client: ClientSessionGenerator, + hass_ws_client: WebSocketGenerator, +) -> None: + """Test user initiated config flow with file upload.""" + + assert await async_setup_component(hass, "http", {}) + assert await async_setup_component(hass, "file_upload", {}) + + result = await hass.config_entries.flow.async_init( + DOMAIN, + context=config_entries.ConfigFlowContext(source=config_entries.SOURCE_USER), + ) + assert result.get(CONF_TYPE) is FlowResultType.MENU + assert result.get("step_id") == "user" + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], user_input={"next_step_id": "upload"} + ) + + assert result.get(CONF_TYPE) is FlowResultType.FORM + assert result.get("step_id") == "upload" + + client = await hass_client() + + with open("tests/components/pdf_scrape/sample.pdf", "rb") as sample_pdf: + os.mkdir(os.path.join(hass.config.path(), ".storage")) + + async with client.post( + "/api/file_upload", data={"file": sample_pdf} + ) as response: + assert response.status == 200 + data = await response.json() + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], user_input={CONF_FILE: data["file_id"]} + ) + + assert result[CONF_TYPE] is FlowResultType.SHOW_PROGRESS + assert result["step_id"] == "upload" + assert result["progress_action"] == "pdf_process" + + while result[CONF_TYPE] is FlowResultType.SHOW_PROGRESS: + await asyncio.sleep(0.1) + result = await hass.config_entries.flow.async_configure(result["flow_id"]) + + assert result[CONF_TYPE] is FlowResultType.CREATE_ENTRY + assert result["subentries"][0]["subentry_type"] == "document" + assert result["result"].data[CONF_TYPE] == ConfType.UPLOAD + next_flow_type, next_flow_id = result["next_flow"] + assert next_flow_type == config_entries.FlowType.CONFIG_SUBENTRIES_FLOW + + # test subentry flow + + result = await hass.config_entries.subentries.async_configure(next_flow_id) + + assert result[CONF_TYPE] is FlowResultType.FORM + assert "target" in result["handler"] + assert result["description_placeholders"]["pages"] == 4 + + # test preview + ws_client = await hass_ws_client(hass) + + await ws_client.send_json( + { + "id": 1, + "type": "target/start_preview", + "flow_id": next_flow_id, + "flow_type": config_entries.FlowType.CONFIG_SUBENTRIES_FLOW, + "user_input": {CONF_PDF_PAGES: "2"}, + } + ) + + ws_response = await ws_client.receive_json() + assert ws_response["id"] == 1 + assert ws_response["success"] + + ws_response = await ws_client.receive_json() + + assert ws_response["id"] == 1 + assert ( + "1\nFoo\nHello, here is some text without a meaning." + in ws_response["event"]["state"] + ) + + result = await hass.config_entries.subentries.async_configure( + next_flow_id, user_input={CONF_PDF_PAGES: "2", CONF_OCR: True} + ) + + assert result[CONF_TYPE] is FlowResultType.SHOW_PROGRESS + assert result["progress_action"] == "getting_pages" + + while result[CONF_TYPE] is FlowResultType.SHOW_PROGRESS: + await asyncio.sleep(0.1) + result = await hass.config_entries.subentries.async_configure(next_flow_id) + + assert result[CONF_TYPE] is FlowResultType.FORM + assert result["step_id"] == "regex" + + assert ( + "1 Foo \n\nHello, here is some text without a meaning." + in result["data_schema"]({})["page_text"] + ) + + # test preview with regex + await ws_client.send_json( + { + "id": 2, + "type": "target/start_preview", + "flow_id": next_flow_id, + "flow_type": config_entries.FlowType.CONFIG_SUBENTRIES_FLOW, + "user_input": {"regex": r"This\stext"}, + } + ) + + ws_response = await ws_client.receive_json() + assert ws_response["id"] == 2 + assert ws_response["success"] + + ws_response = await ws_client.receive_json() + assert ws_response["id"] == 2 + + response = await hass.config_entries.subentries.async_configure( + next_flow_id, user_input={"regex": r"This text should show"} + ) From e6cabb0a239f7ac89c679d6d533fd6a22814c4f8 Mon Sep 17 00:00:00 2001 From: Grant Ellsworth Date: Fri, 5 Jun 2026 08:48:42 -0400 Subject: [PATCH 4/6] Interim updates --- custom_components/pdf_scrape/__init__.py | 168 +++++++++----------- custom_components/pdf_scrape/config_flow.py | 11 +- custom_components/pdf_scrape/coordinator.py | 17 +- custom_components/pdf_scrape/pdf.py | 21 +-- 4 files changed, 99 insertions(+), 118 deletions(-) diff --git a/custom_components/pdf_scrape/__init__.py b/custom_components/pdf_scrape/__init__.py index 0159565..3837e84 100644 --- a/custom_components/pdf_scrape/__init__.py +++ b/custom_components/pdf_scrape/__init__.py @@ -1,8 +1,5 @@ """PDF Scrape Integration.""" -from asyncio import TaskGroup -from collections.abc import Awaitable, Callable -from functools import partial import logging from pathlib import Path from typing import Any @@ -23,6 +20,7 @@ ServiceCall, ServiceResponse, SupportsResponse, + callback, ) from homeassistant.exceptions import ConfigEntryError, ServiceValidationError import homeassistant.helpers.config_validation as cv @@ -54,7 +52,6 @@ PDF, FileError, HTTPError, - PDFParseError, PDFScrapeFile, PDFScrapeHTTP, PDFScrapeUpload, @@ -68,13 +65,6 @@ CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN) -async def async_run_in_loop[*_Ts, _T]( - hass: HomeAssistant, target: Callable[[*_Ts], _T], *args: *_Ts -) -> Awaitable[_T]: - """Run a function in the executor.""" - return await hass.async_add_executor_job(target, *args) - - async def async_setup(hass: HomeAssistant, config_type: ConfigType) -> bool: """Setup service.""" @@ -97,24 +87,20 @@ async def upload_pdf(call: ServiceCall) -> ServiceResponse: with await hass.async_add_executor_job( process_uploaded_file, hass, call.data[CONF_FILE] ) as pdf_path: - try: - pdf: PDFScrapeUpload = await PDFScrapeUpload.pdfscrape( - call.hass, - path=pdf_path, - config_entry_id=config_entry.entry_id, - ) - # Reload the config entry to pick up the new file - hass.config_entries.async_schedule_reload(config_entry.entry_id) - if pdf.pdf.modified is not None: - return { - CONF_MODIFIED: pdf.pdf.modified.isoformat(), - CONF_MODIFIED_SOURCE: pdf.pdf.modified_source, - CONF_SHA256_CHECKSUM: pdf.pdf.md5_checksum, - } - error = "Unable to parse uploaded PDF" - except PDFParseError as ex: - _LOGGER.exception() - error = f"Unable to parse uploaded PDF {ex}" + pdf: PDFScrapeUpload = await PDFScrapeUpload.pdfscrape( + call.hass, + path=pdf_path, + config_entry_id=config_entry.entry_id, + ) + # Reload the config entry to pick up the new file + hass.config_entries.async_schedule_reload(config_entry.entry_id) + if pdf.pdf.modified is not None: + return { + CONF_MODIFIED: pdf.pdf.modified.isoformat(), + CONF_MODIFIED_SOURCE: pdf.pdf.modified_source, + CONF_SHA256_CHECKSUM: pdf.pdf.md5_checksum, + } + error = "Unable to parse uploaded PDF" else: error = "Invalid config_entry_id or device_id" raise ServiceValidationError( @@ -165,21 +151,29 @@ def _one_of(data: dict[str, Any]) -> dict[str, Any]: for entry in hass.config_entries.async_entries(DOMAIN) ] path: Path = Path(hass.config.path(STORAGE_DIR)) - async with TaskGroup() as tg: - for file in await hass.async_add_executor_job(path.iterdir): - if file.is_file() and file.name.startswith(f"{DOMAIN}_"): - entry_or_flow_id: str = file.name.removeprefix(f"{DOMAIN}_") - if entry_or_flow_id not in config_entry_ids and ( - store := get_store(hass, entry_or_flow_id) - ): - _LOGGER.warning( - "Removing orphaned store: %s. Note: This is not an error but indicates that the store is not associated with any config entry", - store.path, - ) - tg.create_task(store.async_remove()) - path = path.joinpath(DOMAIN) - if await hass.async_add_executor_job(path.exists): - for file in await hass.async_add_executor_job(path.iterdir): + + @callback + def _cleanup_orphaned_stores() -> None: + """Wrapper function for blocking code.""" + if path.exists(): + for file in path.iterdir(): + if file.is_file() and file.name.startswith(f"{DOMAIN}_"): + entry_or_flow_id: str = file.name.removeprefix(f"{DOMAIN}_") + if entry_or_flow_id not in config_entry_ids: + _LOGGER.warning( + "Removing orphaned store: %s. Note: This is not an error but indicates that the store is not associated with any config entry", + file, + ) + file.unlink() + + await hass.async_add_executor_job(_cleanup_orphaned_stores) + + path = path.joinpath(DOMAIN) + + def _cleanup_orphaned_files() -> None: + """Wrapper function for blocking code.""" + if path.exists(): + for file in path.iterdir(): if ( file.suffix in [".pdf", ".webp"] and file.stem not in config_entry_ids @@ -188,7 +182,9 @@ def _one_of(data: dict[str, Any]) -> dict[str, Any]: "Removing orphaned file: %s. Note: This is not an error but indicates that the file is not associated with any config entry", file, ) - tg.create_task(async_run_in_loop(hass, file.unlink)) + file.unlink() + + await hass.async_add_executor_job(_cleanup_orphaned_files) hass.http.register_view(PDFView(hass)) @@ -226,29 +222,21 @@ async def async_setup_entry( ) # rename the pdf file. path: Path = Path(hass.config.path(STORAGE_DIR), DOMAIN) - async with TaskGroup() as tg: - tg.create_task( - async_run_in_loop( - hass, - partial( - path.joinpath(f"{temp_key}.pdf").rename, - path.joinpath( - f"{config_entry.entry_id}.pdf" - ), - ), - ) - ) - tg.create_task( - async_run_in_loop( - hass, - partial( - path.joinpath(f"{temp_key}.webp").rename, - path.joinpath( - f"{config_entry.entry_id}.webp" - ), - ), - ) - ) + + def _rename_files() -> None: + """Wrapper function for blocking code.""" + if path.exists(): + for file in path.iterdir(): + if file.stem == temp_key and file.suffix in [ + ".pdf", + ".webp", + ]: + new_name = ( + f"{config_entry.entry_id}{file.suffix}" + ) + file.rename(path.joinpath(new_name)) + + await hass.async_add_executor_job(_rename_files) else: raise ConfigEntryError("Temp store empty") else: @@ -272,7 +260,7 @@ async def async_setup_entry( await hass.config_entries.async_forward_entry_setups(config_entry, _PLATFORMS) - except (HTTPError, TimeoutError, PDFParseError, FileError) as ex: + except (HTTPError, TimeoutError, FileError) as ex: async_raise_error( hass=hass, error_key=ErrorTypes.PDF_ERROR, @@ -280,8 +268,6 @@ async def async_setup_entry( exception=ex, ) - config_entry.async_on_unload(config_entry.add_update_listener(update_listener)) - return True @@ -291,28 +277,32 @@ async def async_remove_config_entry_device( """Handle pre-device delete checks.""" -async def update_listener(hass: HomeAssistant, config_entry: ConfigEntry): - """Process update (when subentries are added).""" - hass.config_entries.async_schedule_reload(config_entry.entry_id) - - async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Unload a config entry.""" return await hass.config_entries.async_unload_platforms(entry, _PLATFORMS) +@callback +def async_cleanup(hass: HomeAssistant, entry_or_flow_id: str) -> None: + """Clean up orphaned files and stores.""" + + path: Path = Path(hass.config.path(STORAGE_DIR), DOMAIN) + + @callback + def _remove_files() -> None: + """Wrapper function for blocking code.""" + if path.exists(): + for file in path.iterdir(): + if file.stem == entry_or_flow_id and file.suffix in [".pdf", ".webp"]: + file.unlink() + + hass.add_job(_remove_files) + if store := get_store(hass, entry_or_flow_id): + hass.async_create_background_task( + store.async_remove(), f"{DOMAIN}.remove_store" + ) + + async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None: """Handle removal of an entry.""" - # Delete the store - await async_cleanup(hass, entry.entry_id) - - -async def async_cleanup(hass: HomeAssistant, entry_or_flow_id: str) -> None: - """Handle cleanup after removed entry and config flow error.""" - # Remove storage files - path: Path = Path(hass.config.path(".storage", DOMAIN)) - async with TaskGroup() as tg: - for file in async_run_in_loop(hass, path.glob(f"{entry_or_flow_id}.*")): - tg.create_task(async_run_in_loop(hass, file.unlink)) - if store := get_store(hass, entry_or_flow_id): - tg.create_task(store.async_remove()) + async_cleanup(hass, entry.entry_id) diff --git a/custom_components/pdf_scrape/config_flow.py b/custom_components/pdf_scrape/config_flow.py index dfd8a4b..1602ac8 100644 --- a/custom_components/pdf_scrape/config_flow.py +++ b/custom_components/pdf_scrape/config_flow.py @@ -90,7 +90,6 @@ from .pdf import ( FileError, HTTPError, - PDFParseError, PDFScrape, PDFScrapeFile, PDFScrapeHTTP, @@ -158,7 +157,7 @@ async def async_step_finish( DOMAIN, f"{ErrorTypes.PDF_ERROR}_{self._get_reconfigure_entry().entry_id}", ) - return self.async_update_and_abort( + return self.async_update_reload_and_abort( self._get_reconfigure_entry(), title=title, data=self.data, @@ -201,9 +200,7 @@ def _async_progress(self) -> ConfigFlowResult | str | None: if exception := self.process_task.exception(): _LOGGER.debug("Progress task exception", exc_info=exception) self.placeholders["msg"] = str(exception) - if isinstance(exception, PDFParseError): - self.reason = "pdf_parse" - elif isinstance(exception, HTTPError): + if isinstance(exception, HTTPError): self.reason = "http_error" elif isinstance(exception, FileError): self.reason = "file_error" @@ -490,6 +487,8 @@ async def async_step_user( self._progress_task = None else: self._progress_task = None + # Save the new pages + await self.pdf.save_to_store() return self.async_show_progress_done(next_step_id="regex") else: return self.async_show_progress( @@ -637,7 +636,7 @@ async def async_step_sensor( f"{error_type}_{self._get_entry().entry_id}_{self._get_reconfigure_subentry().subentry_id}", ): ir.async_delete_issue(self.hass, DOMAIN, issue.issue_id) - return self.async_update_and_abort( + return self.async_update_reload_and_abort( self._get_entry(), self._get_reconfigure_subentry(), title=user_input[CONF_NAME], diff --git a/custom_components/pdf_scrape/coordinator.py b/custom_components/pdf_scrape/coordinator.py index 73ebd93..eb9e4f1 100644 --- a/custom_components/pdf_scrape/coordinator.py +++ b/custom_components/pdf_scrape/coordinator.py @@ -25,14 +25,7 @@ DOMAIN, ErrorTypes, ) -from .pdf import ( - HTTPError, - PDFParseError, - PDFScrape, - PDFScrapeFile, - PDFScrapeHTTP, - PDFScrapeUpload, -) +from .pdf import HTTPError, PDFScrape, PDFScrapeFile, PDFScrapeHTTP, PDFScrapeUpload _LOGGER: logging.Logger = logging.getLogger(__name__) @@ -138,7 +131,7 @@ async def _async_update_data(self) -> dict[str, str]: config_subentry=subentry_conf, ) self.data[subentry_key] = txt - except (HTTPError, PDFParseError) as ex: + except HTTPError as ex: if isinstance(ex, HTTPError) and self.http_error_count < 3: self.http_error_count += 1 raise UpdateFailed(retry_after=30) from ex @@ -223,11 +216,7 @@ def async_raise_error( ) msg: str = "" if exception is not None: - msg = ( - str(exception) - if not isinstance(exception, PDFParseError) - else "Unable to parse pdf" - ) + msg = str(exception) translation_placeholders["msg"] = msg data: dict[str, Any] = { "entry_id": config_entry.entry_id, diff --git a/custom_components/pdf_scrape/pdf.py b/custom_components/pdf_scrape/pdf.py index 70d2108..018f219 100644 --- a/custom_components/pdf_scrape/pdf.py +++ b/custom_components/pdf_scrape/pdf.py @@ -220,7 +220,7 @@ async def _process_pdf( if len(self.pdf.pages) > 0: # already loaded pages, do we need to re-ocr them? await self._get_pages(set(self.pdf.pdf.pages.keys()), update=True) - await self.store.async_save(self.pdf.model_dump()) + await self.save_to_store() # Generate a thumbnail pixmap: Pixmap = await self.hass.async_add_executor_job( self._document[0].get_pixmap @@ -272,6 +272,11 @@ async def close(self) -> None: if hasattr(self, "_stream") and not self._stream.closed: self._stream.close() + async def save_to_store(self) -> None: + """Save the PDF to the store.""" + if self.store is not None: + await self.store.async_save(self.pdf.model_dump()) + async def _get_pages( self, page_nums: set[int], @@ -338,10 +343,12 @@ async def _get_page_text(self, page_index: int, ocr: bool = False) -> str: """Get text from a specific page.""" await self._load_document_from_file_or_cache() if not ocr: - text_page: TextPage = await self.hass.async_add_executor_job( - self._document[page_index].get_textpage - ) - return await self.hass.async_add_executor_job(text_page.extractText) + + def wrap_extract_text() -> str: + text_page: TextPage = self._document[page_index].get_textpage() + return text_page.extractText() + + return await self.hass.async_add_executor_job(wrap_extract_text) return await self.hass.async_add_executor_job( partial( to_text, @@ -566,10 +573,6 @@ def __repr__(self): return f"PDF Uploaded - {self.pdf.title}" if self.pdf.title else "PDF Uploaded" -class PDFParseError(Exception): - """Unable to parse pdf.""" - - class StoredFileError(Exception): """Error accessing the parsed pdf.""" From b7508c30df604348080bfff24872713664a53caa Mon Sep 17 00:00:00 2001 From: Grant Ellsworth Date: Fri, 4 Sep 2026 10:36:46 -0400 Subject: [PATCH 5/6] DeviceRegistry Changes --- custom_components/pdf_scrape/__init__.py | 67 ++++++++++++++----- custom_components/pdf_scrape/config_flow.py | 11 +-- custom_components/pdf_scrape/const.py | 7 -- custom_components/pdf_scrape/image.py | 22 +++--- custom_components/pdf_scrape/manifest.json | 4 +- custom_components/pdf_scrape/sensor.py | 41 +++--------- .../pdf_scrape/translations/en.json | 8 +-- hacs.json | 2 +- 8 files changed, 82 insertions(+), 80 deletions(-) diff --git a/custom_components/pdf_scrape/__init__.py b/custom_components/pdf_scrape/__init__.py index 3837e84..18af5e5 100644 --- a/custom_components/pdf_scrape/__init__.py +++ b/custom_components/pdf_scrape/__init__.py @@ -25,6 +25,7 @@ from homeassistant.exceptions import ConfigEntryError, ServiceValidationError import homeassistant.helpers.config_validation as cv import homeassistant.helpers.device_registry as dr +from homeassistant.helpers.network import get_url from homeassistant.helpers.selector import FileSelector, FileSelectorConfig from homeassistant.helpers.storage import STORAGE_DIR, Store from homeassistant.helpers.typing import ConfigType @@ -34,7 +35,6 @@ CONF_MODIFIED, CONF_MODIFIED_SOURCE, CONF_SHA256_CHECKSUM, - DOCUMENT_SUBENTRY, DOMAIN, ConfType, ErrorTypes, @@ -121,7 +121,7 @@ def _one_of(data: dict[str, Any]) -> dict[str, Any]: raise vol.Invalid("Either device_id or config_entry_id must be specified.") return data - SCHEMA: vol.Schema = vol.Schema( + schema: vol.Schema = vol.Schema( vol.All( { vol.Optional(ATTR_CONFIG_ENTRY_ID): vol.All(cv.ensure_list, _only_one), @@ -138,7 +138,7 @@ def _one_of(data: dict[str, Any]) -> dict[str, Any]: DOMAIN, "upload_pdf", upload_pdf, - SCHEMA, + schema, SupportsResponse.OPTIONAL, ) @@ -195,8 +195,7 @@ async def async_setup_entry( hass: HomeAssistant, config_entry: PDFScrapeConfigEntry ) -> bool: """Set up the config entry.""" - if not config_entry.get_subentries_of_type(DOCUMENT_SUBENTRY.subentry_type): - hass.config_entries.async_add_subentry(config_entry, DOCUMENT_SUBENTRY) + try: coordinator: PDFScrapeCoordinator match config_entry.data[CONF_TYPE]: @@ -258,6 +257,25 @@ def _rename_files() -> None: config_entry.runtime_data = coordinator + device_info = dr.DeviceInfo( + identifiers={(DOMAIN, config_entry.entry_id)}, + name=config_entry.title, + entry_type=dr.DeviceEntryType.SERVICE, + configuration_url=f"{get_url(config_entry.runtime_data.hass)}/api/pdf_scrape/pdf/{config_entry.entry_id}.pdf?token={config_entry.runtime_data.access_token}", + ) + match config_entry.data[CONF_TYPE]: + case ConfType.LOCAL: + device_info["model"] = config_entry.data[CONF_FILE] + case ConfType.HTTP: + device_info["configuration_url"] = config_entry.data[CONF_URL] + device_info["model"] = config_entry.data[CONF_URL] + case ConfType.UPLOAD: + device_info["model"] = config_entry.title + dev_reg = dr.async_get(hass) + dev_reg.async_get_or_create( + config_entry_id=config_entry.entry_id, **device_info + ) + await hass.config_entries.async_forward_entry_setups(config_entry, _PLATFORMS) except (HTTPError, TimeoutError, FileError) as ex: @@ -271,10 +289,28 @@ def _rename_files() -> None: return True -async def async_remove_config_entry_device( - hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.DeviceEntry +async def async_migrate_entry( + hass: HomeAssistant, config_entry: PDFScrapeConfigEntry ) -> bool: - """Handle pre-device delete checks.""" + """Migrate old entry.""" + + if config_entry.version == 1 and config_entry.minor_version == 2: + _LOGGER.debug( + "Migrating configuration from version %s.%s", + config_entry.version, + config_entry.minor_version, + ) + for subentry_id, subentry in config_entry.subentries.items(): + if subentry.subentry_type == "document": + hass.config_entries.async_remove_subentry(config_entry, subentry_id) + break + _LOGGER.debug( + "Migration to configuration version %s.%s successful", + config_entry.version, + config_entry.minor_version, + ) + + return True async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: @@ -288,19 +324,16 @@ def async_cleanup(hass: HomeAssistant, entry_or_flow_id: str) -> None: path: Path = Path(hass.config.path(STORAGE_DIR), DOMAIN) - @callback - def _remove_files() -> None: + async def _remove_files() -> None: """Wrapper function for blocking code.""" - if path.exists(): - for file in path.iterdir(): + if await hass.async_add_executor_job(path.exists): + for file in await hass.async_add_executor_job(path.iterdir): if file.stem == entry_or_flow_id and file.suffix in [".pdf", ".webp"]: - file.unlink() + await hass.async_add_executor_job(file.unlink) - hass.add_job(_remove_files) + hass.create_task(_remove_files(), f"{DOMAIN}._remove_files") if store := get_store(hass, entry_or_flow_id): - hass.async_create_background_task( - store.async_remove(), f"{DOMAIN}.remove_store" - ) + hass.create_task(store.async_remove(), f"{DOMAIN}.remove_store") async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None: diff --git a/custom_components/pdf_scrape/config_flow.py b/custom_components/pdf_scrape/config_flow.py index 1602ac8..66d9e4c 100644 --- a/custom_components/pdf_scrape/config_flow.py +++ b/custom_components/pdf_scrape/config_flow.py @@ -80,7 +80,6 @@ CONF_REGEX_MATCH_INDEX, CONF_REGEX_SEARCH, CONF_VALUE_TEMPLATE, - DOCUMENT_SUBENTRY, DOMAIN, REGEX_PAGE_RANGE_PATTERN, URL_FILE_INTEGRATION, @@ -103,7 +102,7 @@ class PDFScrapeConfigFlow(ConfigFlow, domain=DOMAIN): """PDF Scrape Config Flow Class.""" VERSION: int = 1 - MINOR_VERSION: int = 2 + MINOR_VERSION: int = 3 data: dict[str, str | timedelta | None] = {} placeholders: dict[str, str] | None = {} @@ -147,11 +146,7 @@ async def async_step_finish( ) title: str = self.data[CONF_NAME] if not self.title_fun else self.title_fun() if self.source == SOURCE_USER: - return self.async_create_entry( - title=title, - data=self.data, - subentries=[DOCUMENT_SUBENTRY.as_dict()], - ) + return self.async_create_entry(title=title, data=self.data) ir.async_delete_issue( self.hass, DOMAIN, @@ -182,7 +177,7 @@ async def async_step_process_error( user_input: dict[str, Any] | None = None, ) -> ConfigFlowResult: """Handle errors during processing.""" - await async_cleanup(self.hass, self.flow_id) + async_cleanup(self.hass, self.flow_id) return self.async_abort( reason=self.reason, description_placeholders=self.placeholders, diff --git a/custom_components/pdf_scrape/const.py b/custom_components/pdf_scrape/const.py index 061fd5e..5cf71fe 100644 --- a/custom_components/pdf_scrape/const.py +++ b/custom_components/pdf_scrape/const.py @@ -5,8 +5,6 @@ from re import Pattern from typing import Final -from homeassistant.config_entries import ConfigSubentry - CONF_DEFAULT_SCAN_INTERVAL: Final[timedelta] = timedelta(minutes=5) CONF_MIN_SCAN_INTERVAL: Final[timedelta] = timedelta(minutes=1) DOMAIN: Final[str] = "pdf_scrape" @@ -42,8 +40,3 @@ class ConfType(StrEnum): HTTP = "http" UPLOAD = "upload" LOCAL = "local" - - -DOCUMENT_SUBENTRY: ConfigSubentry = ConfigSubentry( - subentry_type="document", title="PDF", unique_id="document", data={} -) diff --git a/custom_components/pdf_scrape/image.py b/custom_components/pdf_scrape/image.py index 063369a..877c64d 100644 --- a/custom_components/pdf_scrape/image.py +++ b/custom_components/pdf_scrape/image.py @@ -7,13 +7,13 @@ from homeassistant.components.image import ImageEntity from homeassistant.const import EntityCategory from homeassistant.core import HomeAssistant, callback +import homeassistant.helpers.device_registry as dr from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from homeassistant.helpers.storage import STORAGE_DIR from homeassistant.helpers.update_coordinator import CoordinatorEntity from .const import DOMAIN from .coordinator import PDFScrapeConfigEntry, PDFScrapeCoordinator -from .sensor import async_get_device_info _LOGGER: logging.Logger = logging.getLogger(__name__) @@ -24,14 +24,14 @@ async def async_setup_entry( async_add_entities: AddConfigEntryEntitiesCallback, ) -> None: """Set up PDFScrape Entity from a subconfig entry.""" - document_subentry_id: str = [ - subentry.subentry_id - for subentry in config_entry.subentries.values() - if subentry.unique_id == "document" - ][0] + + dev_reg = dr.async_get(hass) + + device_entry = dev_reg.async_get_device_by_identifier( + (DOMAIN, config_entry.entry_id), config_entry.entry_id + ) async_add_entities( - [PDFImageEntity(config_entry.runtime_data)], - config_subentry_id=document_subentry_id, + [PDFImageEntity(config_entry.runtime_data, device_entry)], ) @@ -39,14 +39,13 @@ class PDFImageEntity(ImageEntity, CoordinatorEntity[PDFScrapeCoordinator]): """Image entity for PDFScrape.""" def __init__( - self, - coordinator: PDFScrapeCoordinator, + self, coordinator: PDFScrapeCoordinator, device_entry: dr.DeviceEntry ) -> None: """Initialize the sensor.""" super().__init__(coordinator.hass) super(ImageEntity, self).__init__(coordinator) - self.device_info = async_get_device_info(coordinator.config_entry) self.hass = coordinator.hass + self.device_entry = device_entry self.unique_id = f"{DOMAIN}_thumbnail_{self.coordinator.config_entry.entry_id}" self._attr_name = "Thumbnail" self.has_entity_name = True @@ -67,6 +66,7 @@ def image(self) -> bytes | None: f"{self.coordinator.config_entry.entry_id}.webp", ), "rb", + encoding="base64", ) as file: return file.read() except FileNotFoundError: diff --git a/custom_components/pdf_scrape/manifest.json b/custom_components/pdf_scrape/manifest.json index 175065d..a95d9a7 100644 --- a/custom_components/pdf_scrape/manifest.json +++ b/custom_components/pdf_scrape/manifest.json @@ -9,6 +9,6 @@ "integration_type": "service", "iot_class": "cloud_polling", "issue_tracker": "https://github.com/iluvdata/pdf_scrpae/issues", - "requirements": ["pymupdf==1.27.2.3","pymupdf4llm==1.27.2.3","rapidocr==3.8.1","onnxruntime==1.25.1"], - "version": "2026.5.0" + "requirements": ["pymupdf==1.28.2","pymupdf4llm==1.28.2","rapidocr==3.9.2","onnxruntime==1.29.0"], + "version": "2026.9.0" } diff --git a/custom_components/pdf_scrape/sensor.py b/custom_components/pdf_scrape/sensor.py index 4c1b641..d092efc 100644 --- a/custom_components/pdf_scrape/sensor.py +++ b/custom_components/pdf_scrape/sensor.py @@ -18,10 +18,8 @@ ) from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import ConfigEntryError -from homeassistant.helpers.device_registry import DeviceEntryType -from homeassistant.helpers.entity import DeviceInfo +import homeassistant.helpers.device_registry as dr from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback -from homeassistant.helpers.network import get_url from homeassistant.helpers.update_coordinator import CoordinatorEntity from . import PDFScrapeConfigEntry @@ -43,37 +41,15 @@ async def async_setup_entry( """Set up PDFScrape Entity from a subconfig entry.""" coordinator: PDFScrapeCoordinator = config_entry.runtime_data + async_add_entities([PDFDocumentSensor(coordinator)]) + for subentry_id, subentry in config_entry.subentries.items(): - if subentry.subentry_type == "document": - async_add_entities( - [PDFDocumentSensor(coordinator)], config_subentry_id=subentry_id - ) - continue async_add_entities( [PDFScrapeSensor(coordinator, subentry)], config_subentry_id=subentry_id, ) -def async_get_device_info(config_entry: PDFScrapeConfigEntry) -> DeviceInfo: - """Get device info for the PDFScrape integration.""" - device_info: DeviceInfo = DeviceInfo( - identifiers={(DOMAIN, config_entry.entry_id)}, - name=config_entry.title, - entry_type=DeviceEntryType.SERVICE, - configuration_url=f"{get_url(config_entry.runtime_data.hass)}/api/pdf_scrape/pdf/{config_entry.entry_id}.pdf?token={config_entry.runtime_data.access_token}", - ) - match config_entry.data[CONF_TYPE]: - case ConfType.LOCAL: - device_info["model"] = config_entry.data[CONF_FILE] - case ConfType.HTTP: - device_info["configuration_url"] = config_entry.data[CONF_URL] - device_info["model"] = config_entry.data[CONF_URL] - case ConfType.UPLOAD: - device_info["model"] = config_entry.title - return device_info - - class PDFDocumentSensor(CoordinatorEntity[PDFScrapeCoordinator], SensorEntity): # type: ignore[reportIncompatibleVariableOverride] """PDFDocument Sensor (to watch for changes).""" @@ -83,8 +59,12 @@ def __init__(self, coordinator: PDFScrapeCoordinator) -> None: self._attr_name = "Last Modified" self._attr_device_class = SensorDeviceClass.TIMESTAMP self.unique_id = f"{DOMAIN}_document_{self.coordinator.config_entry.entry_id}" + dev_reg = dr.async_get(coordinator.hass) + self.device_entry = dev_reg.async_get_device_by_identifier( + (DOMAIN, coordinator.config_entry.entry_id), + coordinator.config_entry.entry_id, + ) self._attr_has_entity_name = True - self._attr_device_info = async_get_device_info(coordinator.config_entry) self._attr_icon = "mdi:update" self._attr_entity_category = EntityCategory.DIAGNOSTIC self._attr_translation_key = "modified" @@ -112,7 +92,9 @@ class PDFScrapeSensor(CoordinatorEntity[PDFScrapeCoordinator], SensorEntity): # """PDFScrape Sensor Entity.""" def __init__( - self, coordinator: PDFScrapeCoordinator, subentry: ConfigSubentry + self, + coordinator: PDFScrapeCoordinator, + subentry: ConfigSubentry, ) -> None: """Initialize PDFScrape Sensor.""" super().__init__(coordinator) @@ -121,7 +103,6 @@ def __init__( self.subentry_id: str = subentry.subentry_id self._attr_name = subentry.title self._attr_has_entity_name = True - self._attr_device_info = async_get_device_info(coordinator.config_entry) self._attr_native_unit_of_measurement = subentry.data.get( CONF_UNIT_OF_MEASUREMENT ) diff --git a/custom_components/pdf_scrape/translations/en.json b/custom_components/pdf_scrape/translations/en.json index 4d89a22..38afeaf 100644 --- a/custom_components/pdf_scrape/translations/en.json +++ b/custom_components/pdf_scrape/translations/en.json @@ -65,10 +65,10 @@ "upload_already_configured": "A PDF with the same sha256 checksum is already uploaded. While there is an exceedingly small chance that 2 different pdf files will have the same checksum it's very unlikely. If you are certain that they pdf files are different, alter the metadata of the pdf file you are uploading which will create a unique checksum.", "file_already_configured": "A PDF @ {file} is already configured", "reconfigure_successful": "PDF Reconfiguration successful.", - "pdf_parse": "[%key:component::pdf_scrape::config::error::pdf_parse%]", - "exception": "[%key:component::pdf_scrape::config::error::exception%]", - "http_error": "[%key:component::pdf_scrape::config::error::http_error%]", - "file_error": "[%key:component::pdf_scrape::config::error::file_error%]" + "pdf_parse": "Cannot parse PDF: {msg}", + "exception": "Error: {msg}", + "http_error": "Cannot access PDF @ provided URL: {msg}", + "file_error": "File access error: {msg}" } }, "config_subentries": { diff --git a/hacs.json b/hacs.json index 1d6e6ca..a34a380 100644 --- a/hacs.json +++ b/hacs.json @@ -1,4 +1,4 @@ { "name": "PDF Scrape", - "homeassistant": "2026.6.0" + "homeassistant": "2026.9.0" } From e541375e9c87f8b700022beccb35a9b6cce43b9e Mon Sep 17 00:00:00 2001 From: Grant Ellsworth Date: Fri, 4 Sep 2026 10:51:57 -0400 Subject: [PATCH 6/6] hassfest error --- custom_components/pdf_scrape/translations/en.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/custom_components/pdf_scrape/translations/en.json b/custom_components/pdf_scrape/translations/en.json index 38afeaf..502156b 100644 --- a/custom_components/pdf_scrape/translations/en.json +++ b/custom_components/pdf_scrape/translations/en.json @@ -72,9 +72,6 @@ } }, "config_subentries": { - "document": { - "entry_type": "PDF Document (do not delete)" - }, "target": { "initiate_flow": { "user": "Add Search Target"