Skip to content

HTMLTextDocument() doesn't necessarily preserve the order of serialized dependencies #94

@cpsievert

Description

@cpsievert

If you run this code numerous times, notice that the ordering of dependencies aren't deterministic. By extension, ordering of "3rd party" HTML dependency Quarto docs with server: shiny also aren't deterministic.

from htmltools import HTMLDependency, HTMLTextDocument
html = '''
<html>
  <head>
      <script type="application/json" data-html-dependency="">
        {"name": "ipywidget-libembed-amd", "version": "1.0.1", "source": {"package": "shinywidgets", "subdir": "static"}, "script": [{"src": "libembed-amd.js"}], "stylesheet": [], "meta": [], "all_files": false, "head": null}
      </script>
      <script type="application/json" data-html-dependency="">
        {"name": "ipywidget-output-binding", "version": "0.3.2.9000", "source": {"package": "shinywidgets", "subdir": "static"}, "script": [{"src": "output.js"}], "stylesheet": [{"href": "shinywidgets.css", "rel": "stylesheet"}], "meta": [], "all_files": false, "head": null}
      </script>
  </head>
  <body></body>
</html>
'''
doc = HTMLTextDocument(html, deps_replace_pattern='NA')
res = doc.render()
print(res["dependencies"])

For example, here is output with the dependency ordering reversed:

[<HTMLDependency "ipywidget-output-binding-0.3.2.9000">, <HTMLDependency "ipywidget-libembed-amd-1.0.1">]

The reason for this is because doing list(set(x)) on a list of strings does not necessarily preserve the original ordering:

# Deduplicate dependencies. htmltools normally would dedupe dependencies, but
# with HTMLTextDocuments, the input HTML would usually have been generated by
# something else (like Quarto) and may not have the dependencies deduped.
dep_strs = list(set(dep_strs))

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions