Repository: pyinstaller/pyinstaller-hooks-contrib (language: python)

Issue:
Trame suite hooks
**Which library is the hook for?**

[All Trame libraries](https://github.com/Kitware?q=trame-). Examples:

- `trame`
- `trame-client`
- `trame-components`
- `trame-datagrid`
- `trame-server`
- `trame-tauri`
- `trame-vtk`
- `trame-vuetify`
- `trame-xterm`

**Have you gotten the library to work with pyinstaller?**

Yes, by creating a hook for each library with the line `datas = collect_data_files("LIBRARY_NAME", subdir="module")`.

**Additional context**

Most (maybe all) Trame libraries have a data folder called `module` that needs to be collected. I was planning to create a bunch of PRs for each repo, but I thought maybe there would be a good way to get all the libraries in one-shot to future proof against new Trame libraries as they frequently come out.


Discussion / hints:
I am happy to implement these hooks, please advise on how I should proceed.
Oh, I just found `trame-vtk` uses the folder name `modules`, not `module` :/
Do those dists install everything under one `trame` importable package, or under separate importable packages (e.g., `trame_client`, `trame_components`, etc.)? If the latter, you will probably need to hook each of them anyway.
They are separate importable packages
They will need separate hooks then, one per importable package. But you can put them all in one PR (separate or one commit, up to you).
Can you assign this issue to me?
> Can you assign this issue to me?

Sure, if it makes any difference.

Fix patch:
diff --git a/.gitignore b/.gitignore
index d34f6029..a1903e19 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,6 +24,7 @@ __pycache__/
 *.pdb
 .cache
 *.prof
+.vscode
 
 # Environments
 .env
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame.py
new file mode 100644
index 00000000..404221a0
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame.py
@@ -0,0 +1,13 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+hiddenimports = ["pkgutil"]
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_client.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_client.py
new file mode 100644
index 00000000..c1340341
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_client.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = collect_data_files("trame_client", subdir="module")
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_code.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_code.py
new file mode 100644
index 00000000..333020b5
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_code.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = [*collect_data_files("trame_code", subdir="module")]
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_components.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_components.py
new file mode 100644
index 00000000..d49cfb4f
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_components.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = collect_data_files("trame_components", subdir="module")
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_datagrid.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_datagrid.py
new file mode 100644
index 00000000..601481cd
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_datagrid.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = collect_data_files("trame_datagrid", subdir="module")
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_deckgl.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_deckgl.py
new file mode 100644
index 00000000..091566ee
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_deckgl.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = collect_data_files("trame_deckgl", subdir="module")
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_formkit.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_formkit.py
new file mode 100644
index 00000000..f6779659
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_formkit.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = [*collect_data_files("trame_formkit", subdir="module")]
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_grid.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_grid.py
new file mode 100644
index 00000000..03731318
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_grid.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = [*collect_data_files("trame_grid", subdir="module")]
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_iframe.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_iframe.py
new file mode 100644
index 00000000..5ee77f77
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_iframe.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = collect_data_files("trame_iframe", subdir="module")
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_keycloak.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_keycloak.py
new file mode 100644
index 00000000..89413a65
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_keycloak.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = collect_data_files("trame_keycloak", subdir="module")
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_leaflet.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_leaflet.py
new file mode 100644
index 00000000..9e2f2952
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_leaflet.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = [*collect_data_files("trame_leaflet", subdir="module")]
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_markdown.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_markdown.py
new file mode 100644
index 00000000..71073799
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_markdown.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = [*collect_data_files("trame_markdown", subdir="module")]
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_matplotlib.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_matplotlib.py
new file mode 100644
index 00000000..63e6e667
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_matplotlib.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = [*collect_data_files("trame_matplotlib", subdir="module")]
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_mesh_streamer.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_mesh_streamer.py
new file mode 100644
index 00000000..b782f7ad
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_mesh_streamer.py
@@ -0,0 +1,16 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+hiddenimports = ["vtk"]
+datas = collect_data_files("trame_mesh_streamer", subdir="module")
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_plotly.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_plotly.py
new file mode 100644
index 00000000..eaa2ecdc
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_plotly.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = collect_data_files("trame_plotly", subdir="module")
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_pvui.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_pvui.py
new file mode 100644
index 00000000..209cd630
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_pvui.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = collect_data_files("trame_pvui", subdir="module")
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_quasar.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_quasar.py
new file mode 100644
index 00000000..3dc1c26f
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_quasar.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = [*collect_data_files("trame_quasar", subdir="module")]
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_rca.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_rca.py
new file mode 100644
index 00000000..b9e5da98
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_rca.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = collect_data_files("trame_rca", subdir="module")
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_router.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_router.py
new file mode 100644
index 00000000..a756569e
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_router.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = collect_data_files("trame_router", subdir="module")
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_simput.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_simput.py
new file mode 100644
index 00000000..d80a7ecf
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_simput.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = collect_data_files("trame_simput", subdir="module")
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_tauri.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_tauri.py
new file mode 100644
index 00000000..af474918
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_tauri.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = collect_data_files("trame_tauri", subdir="module")
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_tweakpane.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_tweakpane.py
new file mode 100644
index 00000000..81c91904
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_tweakpane.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = [*collect_data_files("trame_tweakpane", subdir="module")]
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vega.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vega.py
new file mode 100644
index 00000000..fe157d26
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vega.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = collect_data_files("trame_vega", subdir="module")
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vtk.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vtk.py
new file mode 100644
index 00000000..865cbd95
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vtk.py
@@ -0,0 +1,18 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = [
+    *collect_data_files("trame_vtk", subdir="modules"),
+    *collect_data_files("trame_vtk", subdir="tools"),
+]
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vtk3d.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vtk3d.py
new file mode 100644
index 00000000..1c857297
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vtk3d.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = collect_data_files("trame_vtk3d", subdir="module")
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vtklocal.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vtklocal.py
new file mode 100644
index 00000000..288e1e87
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vtklocal.py
@@ -0,0 +1,16 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+hiddenimports = ["vtk"]
+datas = collect_data_files("trame_vtklocal", subdir="module")
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vuetify.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vuetify.py
new file mode 100644
index 00000000..4ea24fc8
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vuetify.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = collect_data_files("trame_vuetify", subdir="module")
diff --git a/_pyinstaller_hooks_contrib/stdhooks/hook-trame_xterm.py b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_xterm.py
new file mode 100644
index 00000000..39c3a720
--- /dev/null
+++ b/_pyinstaller_hooks_contrib/stdhooks/hook-trame_xterm.py
@@ -0,0 +1,15 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.hooks import collect_data_files
+
+datas = collect_data_files("trame_xterm", subdir="module")
diff --git a/news/775.new.rst b/news/775.new.rst
new file mode 100644
index 00000000..bceb696d
--- /dev/null
+++ b/news/775.new.rst
@@ -0,0 +1,1 @@
+Added hooks for the ``trame`` suite of libraries, which has data files and hidden imports.


Test patch:
diff --git a/requirements-test-libraries.txt b/requirements-test-libraries.txt
index 1a3d603f..be151f32 100644
--- a/requirements-test-libraries.txt
+++ b/requirements-test-libraries.txt
@@ -54,6 +54,7 @@ markdown==3.6
 moviepy==1.0.3
 mnemonic==0.21
 msoffcrypto-tool==5.4.1
+nest-asyncio==1.6.0
 netCDF4==1.7.1.post1; python_version >= '3.9'
 numba==0.60.0; python_version >= '3.9'
 numcodecs==0.13.0; python_version >= '3.10'
@@ -88,6 +89,7 @@ pymssql==2.3.0
 pystray==0.19.5
 pythonnet==3.0.3
 pytz==2024.1
+pyvista==0.44.1
 pyzmq==26.1.0
 PyQt5==5.15.11
 qtmodern==0.2.0
@@ -103,9 +105,39 @@ swagger-spec-validator==3.0.4
 tableauhyperapi==0.0.19691
 thinc==9.0.0; python_version >= '3.9'
 timezonefinder==6.5.2; python_version > '3.8'
+trame==3.6.3
+trame-client==3.2.1
+trame-code==1.0.1
+trame-components==2.4.0
+trame-datagrid==0.2.1
+trame-deckgl==2.0.3
+trame-formkit==0.1.2
+trame-grid-layout==1.0.3
+trame-iframe==1.0.1
+trame-keycloak==0.1.1
+trame-leaflet==1.1.1
+trame-markdown==3.0.1
+trame-matplotlib==2.0.3
+trame-mesh-streamer==0.1.0
+trame-plotly==3.0.2
+trame-pvui==0.1.1
+trame-quasar==0.2.1
+trame-rca==0.4.4
+trame-router==2.3.0
+trame-server==3.0.3
+trame-simput==2.4.3
+trame-tauri==0.6.1
+trame-tweakpane==0.1.3
+trame-vega==2.1.1
+trame-vtk==2.8.9
+trame-vtk3d==0.1.0
+trame-vtklocal==0.3.3
+trame-vuetify==2.6.2
+trame-xterm==0.2.1
 Twisted==24.3.0
 tzdata==2024.1
 Unidecode==1.3.8
+vtk==9.3.1
 weasyprint==62.3; python_version >= '3.9'
 web3==6.20.1
 websockets==12.0
diff --git a/tests/test_trame.py b/tests/test_trame.py
new file mode 100644
index 00000000..b6e4f6fe
--- /dev/null
+++ b/tests/test_trame.py
@@ -0,0 +1,663 @@
+# ------------------------------------------------------------------
+# Copyright (c) 2024 PyInstaller Development Team.
+#
+# This file is distributed under the terms of the GNU General Public
+# License (version 2.0 or later).
+#
+# The full license is available in LICENSE, distributed with
+# this software.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+# ------------------------------------------------------------------
+
+from PyInstaller.utils.tests import importorskip
+
+
+@importorskip("trame")
+def test_trame(pyi_builder):
+    pyi_builder.test_source("""
+        import trame
+    """)
+
+
+@importorskip('trame_client')
+def test_trame_client(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip('trame_vuetify')
+def test_trame_vuetify(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.vuetify3 import VAppLayout
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        VAppLayout(server)
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("vtkmodules")
+@importorskip("trame_vtk")
+def test_trame_vtk(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_vtk.widgets import vtk
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            vtk.VtkMesh("test")
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("pyvista")
+@importorskip("vtkmodules")
+@importorskip("nest_asyncio")
+@importorskip("trame_vtk")
+def test_trame_vtk_tools(pyi_builder, tmp_path):
+    pyi_builder.test_source("""
+        import os
+        import sys
+        from pathlib import Path
+
+        import pyvista as pv
+        import trame_vtk
+
+        path = Path(sys.argv[-1]) / "test.html"
+        plotter = pv.Plotter()
+        plotter.export_html(path)  # Uses trame_vtk
+        path.unlink()
+    """, app_args=[tmp_path])
+
+
+@importorskip("trame_xterm")
+def test_trame_xterm(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_xterm.widgets import xterm
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            xterm.XTerm()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("trame_components")
+def test_trame_components(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_components.widgets import trame
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            trame.FloatCard()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("trame_datagrid")
+def test_trame_datagrid(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_datagrid.widgets import datagrid
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            datagrid.VGrid()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("trame_tauri")
+def test_trame_tauri(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_tauri.widgets import tauri
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            tauri.Dialog()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("trame_quasar")
+def test_trame_quasar(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.quasar import QLayout
+        from trame_quasar.widgets import quasar
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with QLayout(server):
+            quasar.QHeader()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("trame_tweakpane")
+def test_trame_tweakpane(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_tweakpane.widgets import tweakpane
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            tweakpane.Tabs()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("trame_deckgl")
+def test_trame_deckgl(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_deckgl.widgets import deckgl
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            deckgl.Deck()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("trame_matplotlib")
+def test_trame_matplotlib(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_matplotlib.widgets import matplotlib
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            matplotlib.Figure()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("trame_vega")
+def test_trame_vega(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_vega.widgets import vega
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            vega.Figure()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("trame_vtk3d")
+def test_trame_vtk3d(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_vtk3d.widgets import vtk3d
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            vtk3d.Vtk3dScene()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("trame_markdown")
+def test_trame_markdown(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_markdown.widgets import markdown
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            markdown.Markdown()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("trame_plotly")
+def test_trame_plotly(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_plotly.widgets import plotly
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            plotly.Figure()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("trame_code")
+def test_trame_code(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_code.widgets import code
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            code.Editor()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("trame_pvui")
+def test_trame_pvui(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_pvui.widgets.colormapper import Colormapper
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            Colormapper()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("vtkmodules")
+@importorskip("trame_mesh_streamer")
+def test_trame_mesh_streamer(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_mesh_streamer.widgets import mesh_streamer
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            mesh_streamer.ProgressiveMesh()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("trame_formkit")
+def test_trame_formkit(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_formkit.widgets import formkit
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            formkit.FormKit()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("trame_grid")
+def test_trame_grid_layout(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_grid.widgets import grid
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            grid.GridLayout()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("trame_iframe")
+def test_trame_iframe(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_iframe.widgets import iframe
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            iframe.IFrame()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("trame_leaflet")
+def test_trame_leaflet(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_leaflet.widgets import leaflet
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            leaflet.LRectangle()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("trame_keycloak")
+def test_trame_keycloak(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_keycloak.widgets import keycloak
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            keycloak.Auth()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("trame_router")
+def test_trame_router(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_router.widgets import router
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            router.RouterView()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+@importorskip("trame_rca")
+def test_trame_rca(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_rca.widgets import rca
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            rca.StatisticsDisplay()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)
+
+
+# The vtklocal package is unstable (currently broken) so no tests can be performed.
+
+
+@importorskip("trame_simput")
+def test_trame_simput(pyi_builder):
+    pyi_builder.test_source("""
+        import asyncio
+
+        from trame.app import get_server
+        from trame.ui.html import DivLayout
+        from trame_simput.widgets import simput
+
+
+        async def stop(*args, **kwargs):
+            await server.stop()
+
+
+        server = get_server()
+        with DivLayout(server):
+            simput.SimputItem()
+        server.controller.on_server_ready.add(
+            lambda *args, **kwargs: asyncio.ensure_future(stop(*args, **kwargs))
+        )
+        server.start(port=0, open_browser=False)
+    """)