From 9d363b30a894ffcd70c3760bf3eb1bdbb3d69bf7 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 22 Sep 2025 10:24:42 +0530 Subject: [PATCH] Only check if name is present in container once Apparently on some windows systems the check fails when run in a thread for mysterious reasons. I cant replicate the failure, but no real harm in this, maybe a very tiny performance decrease at worst. --- src/calibre/srv/render_book.py | 50 +++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/src/calibre/srv/render_book.py b/src/calibre/srv/render_book.py index eb2883e17c..7a7a166b8c 100644 --- a/src/calibre/srv/render_book.py +++ b/src/calibre/srv/render_book.py @@ -71,7 +71,7 @@ def decode_url(x): return decode_component(parts[0]), (parts[1] if len(parts) > 1 else '') -def create_link_replacer(container, link_uid, changed): +def create_link_replacer(container, link_uid, changed, present_names): resource_template = link_uid + '|{}|' def link_replacer(base, url): @@ -94,7 +94,7 @@ def create_link_replacer(container, link_uid, changed): url, frag = purl.path, purl.fragment name = container.href_to_name(url, base) if name: - if container.has_name_and_is_not_empty(name): + if name in present_names: frag = urlunquote(frag) url = resource_template.format(encode_url(name, frag)) else: @@ -258,12 +258,12 @@ def create_cover_page(container, input_fmt, is_comic, book_metadata=None): return raster_cover_name, titlepage_name -def transform_style_sheet(container, name, link_uid, virtualize_resources, virtualized_names): +def transform_style_sheet(container, name, link_uid, virtualize_resources, virtualized_names, present_names): changed = False link_replacer = None if virtualize_resources: changed_names = set() - link_replacer = partial(create_link_replacer(container, link_uid, changed_names), name) + link_replacer = partial(create_link_replacer(container, link_uid, changed_names, present_names), name) raw = container.raw_data(name, decode=True) nraw = transform_properties(raw, is_declaration=False, url_callback=link_replacer) if virtualize_resources: @@ -282,10 +282,10 @@ def transform_style_sheet(container, name, link_uid, virtualize_resources, virtu f.write(raw.encode('utf-8')) -def transform_svg_image(container, name, link_uid, virtualize_resources, virtualized_names): +def transform_svg_image(container, name, link_uid, virtualize_resources, virtualized_names, present_names): if not virtualize_resources: return - link_replacer = create_link_replacer(container, link_uid, set()) + link_replacer = create_link_replacer(container, link_uid, set(), present_names) xlink = XLINK('href') altered = False xlink_xpath = XPath('//*[@xl:href]') @@ -326,7 +326,7 @@ def parse_smil_time(x): return seconds -def transform_smil(container, name, link_uid, virtualize_resources, virtualized_names, smil_map): +def transform_smil(container, name, link_uid, virtualize_resources, virtualized_names, smil_map, present_names): root = container.parsed(name) text_tag, audio_tag = SMIL('text'), SMIL('audio') body_tag, seq_tag, par_tag = SMIL('body'), SMIL('seq'), SMIL('par') @@ -419,7 +419,7 @@ def transform_inline_styles(container, name, transform_sheet, transform_style): return changed -def transform_html(container, name, virtualize_resources, link_uid, link_to_map, virtualized_names): +def transform_html(container, name, virtualize_resources, link_uid, link_to_map, virtualized_names, present_names): link_xpath = XPath('//h:*[@href and (self::h:a or self::h:area)]') svg_link_xpath = XPath('//svg:a') img_xpath = XPath('//h:img[@src]') @@ -427,7 +427,7 @@ def transform_html(container, name, virtualize_resources, link_uid, link_to_map, res_link_xpath = XPath('//h:link[@href]') root = container.parsed(name) changed_names = set() - link_replacer = create_link_replacer(container, link_uid, changed_names) + link_replacer = create_link_replacer(container, link_uid, changed_names, present_names) # Used for viewing images for img in img_xpath(root): @@ -464,7 +464,7 @@ def transform_html(container, name, virtualize_resources, link_uid, link_to_map, transform_inline_styles(container, name, transform_sheet=transform_sheet, transform_style=transform_declaration) if virtualize_resources: - virtualize_html(container, name, link_uid, link_to_map, virtualized_names) + virtualize_html(container, name, link_uid, link_to_map, virtualized_names, present_names) else: def handle_link(a, attr='href'): @@ -497,12 +497,12 @@ def transform_html(container, name, virtualize_resources, link_uid, link_to_map, f.write(shtml) -def virtualize_html(container, name, link_uid, link_to_map, virtualized_names): +def virtualize_html(container, name, link_uid, link_to_map, virtualized_names, present_names): changed = set() link_xpath = XPath('//h:*[@href and (self::h:a or self::h:area)]') svg_link_xpath = XPath('//svg:a') - link_replacer = create_link_replacer(container, link_uid, changed) + link_replacer = create_link_replacer(container, link_uid, changed, present_names) virtualized_names.add(name) root = container.parsed(name) @@ -542,7 +542,7 @@ def virtualize_html(container, name, link_uid, link_to_map, virtualized_names): __smil_file_names__ = '' -def process_book_file(virtualize_resources, link_uid, container, name): +def process_book_file(virtualize_resources, link_uid, container, present_names, name): link_to_map = {} html_data = {} smil_map = {__smil_file_names__: []} @@ -556,14 +556,14 @@ def process_book_file(virtualize_resources, link_uid, container, name): 'has_maths': check_for_maths(root), 'anchor_map': anchor_map(root) } - transform_html(container, name, virtualize_resources, link_uid, link_to_map, virtualized_names) + transform_html(container, name, virtualize_resources, link_uid, link_to_map, virtualized_names, present_names) elif mt in OEB_STYLES: - transform_style_sheet(container, name, link_uid, virtualize_resources, virtualized_names) + transform_style_sheet(container, name, link_uid, virtualize_resources, virtualized_names, present_names) elif mt == 'image/svg+xml': - transform_svg_image(container, name, link_uid, virtualize_resources, virtualized_names) + transform_svg_image(container, name, link_uid, virtualize_resources, virtualized_names, present_names) elif mt in ('application/smil', 'application/smil+xml'): smil_map[__smil_file_names__].append(name) - transform_smil(container, name, link_uid, virtualize_resources, virtualized_names, smil_map) + transform_smil(container, name, link_uid, virtualize_resources, virtualized_names, smil_map, present_names) return link_to_map, html_data, virtualized_names, smil_map @@ -599,10 +599,16 @@ def process_exploded_book( # We do not add zero byte sized files as the IndexedDB API in the # browser has no good way to distinguish between zero byte files and # load failures. - excluded_names = { - name for name, mt in container.mime_map.items() if - name == container.opf_name or mt == guess_type('a.ncx') or name.startswith('META-INF/') or - name == 'mimetype' or not container.has_name_and_is_not_empty(name)} + excluded_names = set() + present_names = set() + for name, mt in container.mime_map.items(): + if container.has_name_and_is_not_empty(name): + present_names.add(name) + if name == container.opf_name or mt == guess_type('a.ncx') or name.startswith( + 'META-INF/') or name == 'mimetype': + excluded_names.add(name) + else: + excluded_names.add(name) raster_cover_name, titlepage_name = create_cover_page(container, input_fmt.lower(), is_comic, book_metadata) tocobj = get_toc(container, verify_destinations=False) @@ -647,7 +653,7 @@ def process_exploded_book( names_that_need_work = tuple(n for n, mt in container.mime_map.items() if needs_work(mt)) num_workers = calculate_number_of_workers(names_that_need_work, container, max_workers) results = [] - f = partial(process_book_file, virtualize_resources, book_render_data['link_uid'], container) + f = partial(process_book_file, virtualize_resources, book_render_data['link_uid'], container, present_names) if num_workers < 2: results.extend(map(f, names_that_need_work)) else: