pyvista-quicklook 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyvista_quicklook-0.2.0/.github/workflows/ci.yml +133 -0
- pyvista_quicklook-0.2.0/.gitignore +10 -0
- pyvista_quicklook-0.2.0/.pre-commit-config.yaml +44 -0
- pyvista_quicklook-0.2.0/LICENSE +21 -0
- pyvista_quicklook-0.2.0/PKG-INFO +231 -0
- pyvista_quicklook-0.2.0/README.md +206 -0
- pyvista_quicklook-0.2.0/macos/App/main.swift +121 -0
- pyvista_quicklook-0.2.0/macos/QuickLookExtension/PreviewViewController.swift +108 -0
- pyvista_quicklook-0.2.0/macos/QuickLookExtension/QuickLook.entitlements +11 -0
- pyvista_quicklook-0.2.0/macos/Shared/Camera.swift +26 -0
- pyvista_quicklook-0.2.0/macos/Shared/Helper.swift +258 -0
- pyvista_quicklook-0.2.0/macos/Tools/RenderScene.swift +76 -0
- pyvista_quicklook-0.2.0/pyproject.toml +116 -0
- pyvista_quicklook-0.2.0/pyvista_quicklook/__init__.py +8 -0
- pyvista_quicklook-0.2.0/pyvista_quicklook/__main__.py +10 -0
- pyvista_quicklook-0.2.0/pyvista_quicklook/_scene_export.py +180 -0
- pyvista_quicklook-0.2.0/pyvista_quicklook/_version.py +24 -0
- pyvista_quicklook-0.2.0/pyvista_quicklook/_warmup.py +46 -0
- pyvista_quicklook-0.2.0/pyvista_quicklook/cli.py +357 -0
- pyvista_quicklook-0.2.0/pyvista_quicklook/config.py +118 -0
- pyvista_quicklook-0.2.0/pyvista_quicklook/convert.py +105 -0
- pyvista_quicklook-0.2.0/pyvista_quicklook/daemon.py +240 -0
- pyvista_quicklook-0.2.0/pyvista_quicklook/formats.py +123 -0
- pyvista_quicklook-0.2.0/pyvista_quicklook/plist.py +108 -0
- pyvista_quicklook-0.2.0/pyvista_quicklook/render.py +175 -0
- pyvista_quicklook-0.2.0/pyvista_quicklook/warmup.py +72 -0
- pyvista_quicklook-0.2.0/pyvista_quicklook.egg-info/PKG-INFO +231 -0
- pyvista_quicklook-0.2.0/pyvista_quicklook.egg-info/SOURCES.txt +40 -0
- pyvista_quicklook-0.2.0/pyvista_quicklook.egg-info/dependency_links.txt +1 -0
- pyvista_quicklook-0.2.0/pyvista_quicklook.egg-info/entry_points.txt +2 -0
- pyvista_quicklook-0.2.0/pyvista_quicklook.egg-info/scm_file_list.json +36 -0
- pyvista_quicklook-0.2.0/pyvista_quicklook.egg-info/scm_version.json +8 -0
- pyvista_quicklook-0.2.0/pyvista_quicklook.egg-info/top_level.txt +1 -0
- pyvista_quicklook-0.2.0/scripts/bootstrap.sh +57 -0
- pyvista_quicklook-0.2.0/scripts/build.sh +90 -0
- pyvista_quicklook-0.2.0/scripts/install.sh +128 -0
- pyvista_quicklook-0.2.0/scripts/uninstall.sh +29 -0
- pyvista_quicklook-0.2.0/setup.cfg +4 -0
- pyvista_quicklook-0.2.0/tests/test_pyvista_quicklook.py +528 -0
- pyvista_quicklook-0.2.0/tests/test_render.py +116 -0
- pyvista_quicklook-0.2.0/tests/test_scene_export.py +170 -0
- pyvista_quicklook-0.2.0/uv.lock +1804 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
# `pull_request` is deliberately unfiltered: filtering it by base branch would
|
|
4
|
+
# skip every pull request in a stack that does not target main.
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
tags: [v*]
|
|
9
|
+
pull_request:
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
pre-commit:
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
23
|
+
with:
|
|
24
|
+
persist-credentials: false
|
|
25
|
+
fetch-depth: 0
|
|
26
|
+
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
27
|
+
with:
|
|
28
|
+
enable-cache: false
|
|
29
|
+
- run: uv sync --group dev
|
|
30
|
+
- run: uv run pre-commit run --all-files --show-diff-on-failure
|
|
31
|
+
env:
|
|
32
|
+
# This hook exists to stop *local* commits straight to main; it
|
|
33
|
+
# would always fail here since CI checks out that branch/tag directly.
|
|
34
|
+
SKIP: no-commit-to-branch
|
|
35
|
+
|
|
36
|
+
test:
|
|
37
|
+
# The helper is pure standard library, so it is tested away from macOS too.
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
strategy:
|
|
40
|
+
fail-fast: false
|
|
41
|
+
matrix:
|
|
42
|
+
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
45
|
+
with:
|
|
46
|
+
persist-credentials: false
|
|
47
|
+
fetch-depth: 0
|
|
48
|
+
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
49
|
+
with:
|
|
50
|
+
enable-cache: false
|
|
51
|
+
- run: uv sync --group dev --python ${{ matrix.python-version }}
|
|
52
|
+
- run: uv run pytest tests/
|
|
53
|
+
|
|
54
|
+
app:
|
|
55
|
+
# Builds the real thing: compiles both Swift targets, generates the
|
|
56
|
+
# Info.plist files, and ad-hoc signs the bundle.
|
|
57
|
+
runs-on: macos-latest
|
|
58
|
+
steps:
|
|
59
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
60
|
+
with:
|
|
61
|
+
persist-credentials: false
|
|
62
|
+
fetch-depth: 0
|
|
63
|
+
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
64
|
+
with:
|
|
65
|
+
enable-cache: false
|
|
66
|
+
- run: uv sync --group dev
|
|
67
|
+
- run: ./scripts/build.sh --universal
|
|
68
|
+
- name: Check the bundle is complete and signed
|
|
69
|
+
run: |
|
|
70
|
+
app=build/PyVistaQuickLook.app
|
|
71
|
+
appex="$app/Contents/PlugIns/PyVistaQuickLookExtension.appex"
|
|
72
|
+
test -x "$app/Contents/MacOS/PyVistaQuickLook"
|
|
73
|
+
test -x "$appex/Contents/MacOS/PyVistaQuickLookExtension"
|
|
74
|
+
codesign --verify --deep --strict "$app"
|
|
75
|
+
# A preview extension is only registered by macOS when it is sandboxed.
|
|
76
|
+
codesign -d --entitlements - "$appex" 2>&1 | grep -q app-sandbox
|
|
77
|
+
# Both architectures, so the download runs on any Mac.
|
|
78
|
+
lipo -archs "$appex/Contents/MacOS/PyVistaQuickLookExtension" | grep -q x86_64
|
|
79
|
+
lipo -archs "$appex/Contents/MacOS/PyVistaQuickLookExtension" | grep -q arm64
|
|
80
|
+
- run: uv run pytest tests/
|
|
81
|
+
- name: Package the app
|
|
82
|
+
run: ditto -c -k --keepParent build/PyVistaQuickLook.app build/PyVistaQuickLook.zip
|
|
83
|
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
84
|
+
with:
|
|
85
|
+
name: PyVistaQuickLook.zip
|
|
86
|
+
path: build/PyVistaQuickLook.zip
|
|
87
|
+
|
|
88
|
+
build:
|
|
89
|
+
needs: [pre-commit, test, app]
|
|
90
|
+
runs-on: ubuntu-latest
|
|
91
|
+
steps:
|
|
92
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
93
|
+
with:
|
|
94
|
+
persist-credentials: false
|
|
95
|
+
fetch-depth: 0
|
|
96
|
+
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
97
|
+
with:
|
|
98
|
+
enable-cache: false
|
|
99
|
+
- run: uv build
|
|
100
|
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
101
|
+
with:
|
|
102
|
+
name: dist
|
|
103
|
+
path: dist/
|
|
104
|
+
|
|
105
|
+
publish:
|
|
106
|
+
needs: build
|
|
107
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
108
|
+
runs-on: ubuntu-latest
|
|
109
|
+
environment: release
|
|
110
|
+
permissions:
|
|
111
|
+
id-token: write
|
|
112
|
+
steps:
|
|
113
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
114
|
+
with:
|
|
115
|
+
name: dist
|
|
116
|
+
path: dist/
|
|
117
|
+
- uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
|
|
118
|
+
|
|
119
|
+
release:
|
|
120
|
+
# Attaches the built app to the tag's release, so installing needs no compiler.
|
|
121
|
+
needs: [app, build]
|
|
122
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
123
|
+
runs-on: ubuntu-latest
|
|
124
|
+
permissions:
|
|
125
|
+
contents: write
|
|
126
|
+
steps:
|
|
127
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
128
|
+
with:
|
|
129
|
+
name: PyVistaQuickLook.zip
|
|
130
|
+
- env:
|
|
131
|
+
GH_TOKEN: ${{ github.token }}
|
|
132
|
+
TAG: ${{ github.ref_name }}
|
|
133
|
+
run: gh release upload "$TAG" PyVistaQuickLook.zip --clobber --repo "$GITHUB_REPOSITORY"
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
ci:
|
|
2
|
+
autoupdate_commit_msg: 'chore: update pre-commit hooks'
|
|
3
|
+
autofix_prs: true
|
|
4
|
+
autoupdate_schedule: quarterly
|
|
5
|
+
|
|
6
|
+
repos:
|
|
7
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
8
|
+
rev: v5.0.0
|
|
9
|
+
hooks:
|
|
10
|
+
- id: check-merge-conflict
|
|
11
|
+
- id: debug-statements
|
|
12
|
+
- id: no-commit-to-branch
|
|
13
|
+
args: [--branch, main]
|
|
14
|
+
|
|
15
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
16
|
+
rev: v0.16.0
|
|
17
|
+
hooks:
|
|
18
|
+
- id: ruff-check
|
|
19
|
+
args: [--fix, --show-fixes]
|
|
20
|
+
- id: ruff-format
|
|
21
|
+
|
|
22
|
+
- repo: https://github.com/zizmorcore/zizmor-pre-commit
|
|
23
|
+
rev: v1.11.0
|
|
24
|
+
hooks:
|
|
25
|
+
- id: zizmor
|
|
26
|
+
|
|
27
|
+
- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
|
|
28
|
+
rev: v2.15.0
|
|
29
|
+
hooks:
|
|
30
|
+
- id: pretty-format-yaml
|
|
31
|
+
args: [--autofix, --indent, '2']
|
|
32
|
+
|
|
33
|
+
- repo: https://github.com/ComPWA/taplo-pre-commit
|
|
34
|
+
rev: v0.9.3
|
|
35
|
+
hooks:
|
|
36
|
+
- id: taplo-format
|
|
37
|
+
# See options: https://taplo.tamasfe.dev/configuration/formatter-options.html
|
|
38
|
+
args: [--option, reorder_arrays=true, --option, reorder_keys=true, --option, align_comments=false]
|
|
39
|
+
|
|
40
|
+
# The app is built and installed by shell scripts, so they are linted too.
|
|
41
|
+
- repo: https://github.com/shellcheck-py/shellcheck-py
|
|
42
|
+
rev: v0.11.0.1
|
|
43
|
+
hooks:
|
|
44
|
+
- id: shellcheck
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Erik Bedard
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to
|
|
7
|
+
deal in the Software without restriction, including without limitation the
|
|
8
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
9
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
20
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
21
|
+
IN THE SOFTWARE.
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyvista-quicklook
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Quick Look previews for PyVista-readable mesh files.
|
|
5
|
+
Author: Erik Bedard
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/user27182/pyvista-quicklook
|
|
8
|
+
Keywords: macos,mesh,preview,pyvista,quicklook,vtk
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Environment :: MacOS X
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
# PyVista Quick Look
|
|
27
|
+
|
|
28
|
+
Press the space bar on a mesh file in the Finder and turn it with the mouse, the same
|
|
29
|
+
way macOS already previews `.ply` and `.usdz` models.
|
|
30
|
+
|
|
31
|
+
Selecting `flow.vtu` and pressing space shows its surface in the Quick Look panel,
|
|
32
|
+
coloured by the active scalars and free to rotate and zoom.
|
|
33
|
+
|
|
34
|
+
## Requirements
|
|
35
|
+
|
|
36
|
+
- macOS 12 or newer
|
|
37
|
+
|
|
38
|
+
Neither PyVista nor a compiler needs to be installed. The installer downloads a
|
|
39
|
+
published build of the app and provisions its own PyVista; Xcode command line tools
|
|
40
|
+
(`xcode-select --install`) are only needed to build from source.
|
|
41
|
+
|
|
42
|
+
## Install
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
./scripts/install.sh
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Then select a `.vtu`, `.vtp`, or `.vtk` file in the Finder and press space.
|
|
49
|
+
|
|
50
|
+
The installer fetches [uv](https://docs.astral.sh/uv/) if it is missing, creates a
|
|
51
|
+
private environment holding PyVista, installs the `pvql` helper, builds and registers
|
|
52
|
+
`PyVistaQuickLook.app`, and loads PyVista once so the first preview is quick. Nothing
|
|
53
|
+
outside `~/Library/Application Support/PyVistaQuickLook`, `~/Applications`, and
|
|
54
|
+
`~/.local/bin` is touched, and no existing Python environment is used or changed.
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
./scripts/install.sh --prefix /Applications # install for all users
|
|
58
|
+
./scripts/install.sh --pyvista /path/to/venv/bin/pyvista # use an existing PyVista
|
|
59
|
+
./scripts/install.sh --app /path/to/PyVistaQuickLook.app # skip the build
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Check the result with `pvql doctor`.
|
|
63
|
+
|
|
64
|
+
`scripts/bootstrap.sh` installs the same way from a URL, once this repository is
|
|
65
|
+
published:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
curl -LsSf https://raw.githubusercontent.com/user27182/pyvista-quicklook/main/scripts/bootstrap.sh | sh
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### What gets installed
|
|
72
|
+
|
|
73
|
+
About 270 MB, in `~/Library/Application Support/PyVistaQuickLook/venv`:
|
|
74
|
+
|
|
75
|
+
- PyVista, from git until 0.49 is released, installed with `--no-deps`
|
|
76
|
+
- [cvista](https://github.com/pyvista/cvista)`[all]`, a VTK fork, in place of stock VTK
|
|
77
|
+
- cyclopts, matplotlib, numpy, pillow, pooch, pyobjc-framework-Cocoa, scooby,
|
|
78
|
+
typing-extensions
|
|
79
|
+
|
|
80
|
+
Installing PyVista with `--no-deps` and swapping stock VTK for cvista is what keeps this
|
|
81
|
+
down; stock VTK alone is 591 MB against cvista's 136 MB.
|
|
82
|
+
|
|
83
|
+
Point `--pyvista` at an environment you already have to use that instead.
|
|
84
|
+
|
|
85
|
+
## Supported files
|
|
86
|
+
|
|
87
|
+
36 extensions are claimed by default, including `.vtk`, `.vti`, `.vtp`, `.vtu`, `.vtm`,
|
|
88
|
+
`.vtkhdf`, `.pvd`, `.case`, `.exo`, `.foam`, `.cgns`, `.segy`, and `.xdmf`.
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
pvql types # what is claimed now
|
|
92
|
+
pvql types --all # every format pvql knows about
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Formats macOS already previews — `.stl`, `.obj`, `.ply`, `.png` — are deliberately not
|
|
96
|
+
claimed, so the built-in viewer keeps handling them. Claim them by adding them to the
|
|
97
|
+
config and reinstalling:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{ "extensions": { "add": [".stl", ".obj"], "remove": [".pdb"] } }
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## How it works
|
|
104
|
+
|
|
105
|
+
The app bundle contains a Quick Look extension that declares a uniform type identifier
|
|
106
|
+
for each claimed extension. When the Finder previews one of those files, the extension
|
|
107
|
+
hands it to a background render service, which reads it with PyVista, extracts the
|
|
108
|
+
surface, colours the vertices by the active scalars, and writes a PLY. The extension
|
|
109
|
+
shows that PLY in a SceneKit view, which is what makes the preview turnable.
|
|
110
|
+
|
|
111
|
+
Datasets with no surface to show fall back to a still image rendered by
|
|
112
|
+
`pyvista plot --off-screen --screenshot`, which keeps the scalar bar and axes that the
|
|
113
|
+
interactive view leaves out. Setting `"interactive": false` in the config always uses
|
|
114
|
+
that still image.
|
|
115
|
+
|
|
116
|
+
Both are cached under `~/Library/Caches/PyVistaQuickLook`, keyed by the file's path,
|
|
117
|
+
size, and modification time, so editing a file invalidates its preview. Later previews
|
|
118
|
+
of the same file come from the cache.
|
|
119
|
+
|
|
120
|
+
Every preview runs PyVista in a fresh process, and VTK is 600 MB of libraries, so the
|
|
121
|
+
first one after a restart is slow until macOS has those pages cached. The service loads
|
|
122
|
+
them in the background when it starts, which is at login and whenever it is reinstalled,
|
|
123
|
+
so that cost is paid before you press space. `pvql warmup` does the same on demand, and
|
|
124
|
+
`"warm_on_start": false` turns the automatic pass off.
|
|
125
|
+
|
|
126
|
+
Cell data is sampled onto the points before colouring. Surfaces are sent whole:
|
|
127
|
+
decimating them costs more time than the larger file does, so `max_scene_points` is a
|
|
128
|
+
safety valve for very large meshes rather than a routine step. Set it to `0` to never
|
|
129
|
+
decimate.
|
|
130
|
+
|
|
131
|
+
When a preview fails, the Quick Look panel shows the error text instead.
|
|
132
|
+
|
|
133
|
+
### The render service
|
|
134
|
+
|
|
135
|
+
macOS runs Quick Look extensions in a sandbox that VTK cannot render inside, so
|
|
136
|
+
rendering happens in a launch agent instead. `scripts/install.sh` sets it up.
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
pvql service # report whether it is loaded
|
|
140
|
+
pvql service --install # (re)install and start it
|
|
141
|
+
pvql service --uninstall
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Its output goes to `~/Library/Logs/pvqld.log`.
|
|
145
|
+
|
|
146
|
+
### Files in the Desktop, Documents, and Downloads folders
|
|
147
|
+
|
|
148
|
+
macOS keeps those folders private to each program, and the render service cannot read
|
|
149
|
+
them. The Quick Look extension copies the file it was asked to preview into its own
|
|
150
|
+
container so that the service can render it anyway.
|
|
151
|
+
|
|
152
|
+
A dataset that points at neighbouring files — `.pvd`, `.vtm`, `.case`, `.foam` — needs
|
|
153
|
+
those neighbours, which the copy does not include. Keep such datasets outside those
|
|
154
|
+
three folders, or grant the render service Full Disk Access in System Settings under
|
|
155
|
+
Privacy & Security.
|
|
156
|
+
|
|
157
|
+
## Configuration
|
|
158
|
+
|
|
159
|
+
`~/Library/Application Support/PyVistaQuickLook/config.json`
|
|
160
|
+
|
|
161
|
+
| Key | Default | Effect |
|
|
162
|
+
| --- | --- | --- |
|
|
163
|
+
| `python` | set at install | Interpreter of the PyVista environment |
|
|
164
|
+
| `pyvista` | unset | Optional `pyvista` executable, for still images |
|
|
165
|
+
| `pvql` | discovered | Absolute path to the `pvql` helper |
|
|
166
|
+
| `interactive` | `true` | Show a turnable surface instead of a still image |
|
|
167
|
+
| `max_scene_points` | `2000000` | Decimate only above this many points; `0` never does |
|
|
168
|
+
| `colormap` | `'viridis'` | Colormap used to colour the surface |
|
|
169
|
+
| `warm_on_start` | `true` | Load PyVista and VTK when the render service starts |
|
|
170
|
+
| `window_size` | `[1024, 1024]` | Rendered preview size in pixels |
|
|
171
|
+
| `timeout` | `60` | Seconds before a render is abandoned |
|
|
172
|
+
| `max_file_size_mb` | `512` | Files above this size show a notice instead of a render |
|
|
173
|
+
| `background` | `null` | Background color passed to `pyvista plot` |
|
|
174
|
+
| `extra_args` | `[]` | Extra arguments appended to `pyvista plot` |
|
|
175
|
+
| `cache` | `true` | Reuse previously rendered previews |
|
|
176
|
+
| `log` | `false` | Append render activity to `pvql.log` beside the config file |
|
|
177
|
+
|
|
178
|
+
Changing `extensions` requires a reinstall, because the claimed types are baked into the
|
|
179
|
+
app bundle. Every other key takes effect on the next preview.
|
|
180
|
+
|
|
181
|
+
## Commands
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
pvql preview FILE # render and print the path of the cached PNG
|
|
185
|
+
pvql warmup # load PyVista and VTK ahead of the first preview
|
|
186
|
+
pvql warm DIR # render a directory ahead of time
|
|
187
|
+
pvql types # list claimed extensions
|
|
188
|
+
pvql doctor # check every part of the integration
|
|
189
|
+
pvql service # manage the render service
|
|
190
|
+
pvql config --init # write a config file with discovered defaults
|
|
191
|
+
pvql cache --clear # delete cached previews
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Troubleshooting
|
|
195
|
+
|
|
196
|
+
Run `pvql doctor` first; it checks the helper, the app, the extension registration, the
|
|
197
|
+
service, and a real render.
|
|
198
|
+
|
|
199
|
+
- **The panel says the service is not answering.** Run `pvql service --install`.
|
|
200
|
+
- **Nothing happens on space bar.** Confirm the type is claimed with `pvql types`, then
|
|
201
|
+
check that Finder resolves it: `mdls -name kMDItemContentType yourfile.vtu` should
|
|
202
|
+
report an `io.github.user27182.pyvista-quicklook.*` type.
|
|
203
|
+
- **Previews are stale.** `pvql cache --clear`.
|
|
204
|
+
- **A render fails.** Set `"log": true` in the config; activity is appended to
|
|
205
|
+
`pvql.log` beside it. The extension's own log is in
|
|
206
|
+
`~/Library/Containers/io.github.user27182.PyVistaQuickLook.QuickLook/Data/tmp/`.
|
|
207
|
+
|
|
208
|
+
## Development
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
uv sync --group dev
|
|
212
|
+
uv run pytest tests/ # helper tests, with coverage
|
|
213
|
+
uv run pre-commit run --all-files
|
|
214
|
+
./scripts/build.sh # compile and sign the app bundle
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
`main` is protected by a pre-commit hook, so work on a branch.
|
|
218
|
+
|
|
219
|
+
Releases are published to PyPI by CI through trusted publishing: push a `v*` tag and
|
|
220
|
+
the `publish` job uploads from the `release` environment. That requires a matching
|
|
221
|
+
pending publisher configured on PyPI for this repository and workflow.
|
|
222
|
+
|
|
223
|
+
## Uninstall
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
./scripts/uninstall.sh
|
|
227
|
+
uv tool uninstall pyvista-quicklook
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
That removes the app, the private PyVista environment, the downloaded source, and the
|
|
231
|
+
cache, leaving only the config file.
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# PyVista Quick Look
|
|
2
|
+
|
|
3
|
+
Press the space bar on a mesh file in the Finder and turn it with the mouse, the same
|
|
4
|
+
way macOS already previews `.ply` and `.usdz` models.
|
|
5
|
+
|
|
6
|
+
Selecting `flow.vtu` and pressing space shows its surface in the Quick Look panel,
|
|
7
|
+
coloured by the active scalars and free to rotate and zoom.
|
|
8
|
+
|
|
9
|
+
## Requirements
|
|
10
|
+
|
|
11
|
+
- macOS 12 or newer
|
|
12
|
+
|
|
13
|
+
Neither PyVista nor a compiler needs to be installed. The installer downloads a
|
|
14
|
+
published build of the app and provisions its own PyVista; Xcode command line tools
|
|
15
|
+
(`xcode-select --install`) are only needed to build from source.
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
./scripts/install.sh
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Then select a `.vtu`, `.vtp`, or `.vtk` file in the Finder and press space.
|
|
24
|
+
|
|
25
|
+
The installer fetches [uv](https://docs.astral.sh/uv/) if it is missing, creates a
|
|
26
|
+
private environment holding PyVista, installs the `pvql` helper, builds and registers
|
|
27
|
+
`PyVistaQuickLook.app`, and loads PyVista once so the first preview is quick. Nothing
|
|
28
|
+
outside `~/Library/Application Support/PyVistaQuickLook`, `~/Applications`, and
|
|
29
|
+
`~/.local/bin` is touched, and no existing Python environment is used or changed.
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
./scripts/install.sh --prefix /Applications # install for all users
|
|
33
|
+
./scripts/install.sh --pyvista /path/to/venv/bin/pyvista # use an existing PyVista
|
|
34
|
+
./scripts/install.sh --app /path/to/PyVistaQuickLook.app # skip the build
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Check the result with `pvql doctor`.
|
|
38
|
+
|
|
39
|
+
`scripts/bootstrap.sh` installs the same way from a URL, once this repository is
|
|
40
|
+
published:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
curl -LsSf https://raw.githubusercontent.com/user27182/pyvista-quicklook/main/scripts/bootstrap.sh | sh
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### What gets installed
|
|
47
|
+
|
|
48
|
+
About 270 MB, in `~/Library/Application Support/PyVistaQuickLook/venv`:
|
|
49
|
+
|
|
50
|
+
- PyVista, from git until 0.49 is released, installed with `--no-deps`
|
|
51
|
+
- [cvista](https://github.com/pyvista/cvista)`[all]`, a VTK fork, in place of stock VTK
|
|
52
|
+
- cyclopts, matplotlib, numpy, pillow, pooch, pyobjc-framework-Cocoa, scooby,
|
|
53
|
+
typing-extensions
|
|
54
|
+
|
|
55
|
+
Installing PyVista with `--no-deps` and swapping stock VTK for cvista is what keeps this
|
|
56
|
+
down; stock VTK alone is 591 MB against cvista's 136 MB.
|
|
57
|
+
|
|
58
|
+
Point `--pyvista` at an environment you already have to use that instead.
|
|
59
|
+
|
|
60
|
+
## Supported files
|
|
61
|
+
|
|
62
|
+
36 extensions are claimed by default, including `.vtk`, `.vti`, `.vtp`, `.vtu`, `.vtm`,
|
|
63
|
+
`.vtkhdf`, `.pvd`, `.case`, `.exo`, `.foam`, `.cgns`, `.segy`, and `.xdmf`.
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
pvql types # what is claimed now
|
|
67
|
+
pvql types --all # every format pvql knows about
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Formats macOS already previews — `.stl`, `.obj`, `.ply`, `.png` — are deliberately not
|
|
71
|
+
claimed, so the built-in viewer keeps handling them. Claim them by adding them to the
|
|
72
|
+
config and reinstalling:
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{ "extensions": { "add": [".stl", ".obj"], "remove": [".pdb"] } }
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## How it works
|
|
79
|
+
|
|
80
|
+
The app bundle contains a Quick Look extension that declares a uniform type identifier
|
|
81
|
+
for each claimed extension. When the Finder previews one of those files, the extension
|
|
82
|
+
hands it to a background render service, which reads it with PyVista, extracts the
|
|
83
|
+
surface, colours the vertices by the active scalars, and writes a PLY. The extension
|
|
84
|
+
shows that PLY in a SceneKit view, which is what makes the preview turnable.
|
|
85
|
+
|
|
86
|
+
Datasets with no surface to show fall back to a still image rendered by
|
|
87
|
+
`pyvista plot --off-screen --screenshot`, which keeps the scalar bar and axes that the
|
|
88
|
+
interactive view leaves out. Setting `"interactive": false` in the config always uses
|
|
89
|
+
that still image.
|
|
90
|
+
|
|
91
|
+
Both are cached under `~/Library/Caches/PyVistaQuickLook`, keyed by the file's path,
|
|
92
|
+
size, and modification time, so editing a file invalidates its preview. Later previews
|
|
93
|
+
of the same file come from the cache.
|
|
94
|
+
|
|
95
|
+
Every preview runs PyVista in a fresh process, and VTK is 600 MB of libraries, so the
|
|
96
|
+
first one after a restart is slow until macOS has those pages cached. The service loads
|
|
97
|
+
them in the background when it starts, which is at login and whenever it is reinstalled,
|
|
98
|
+
so that cost is paid before you press space. `pvql warmup` does the same on demand, and
|
|
99
|
+
`"warm_on_start": false` turns the automatic pass off.
|
|
100
|
+
|
|
101
|
+
Cell data is sampled onto the points before colouring. Surfaces are sent whole:
|
|
102
|
+
decimating them costs more time than the larger file does, so `max_scene_points` is a
|
|
103
|
+
safety valve for very large meshes rather than a routine step. Set it to `0` to never
|
|
104
|
+
decimate.
|
|
105
|
+
|
|
106
|
+
When a preview fails, the Quick Look panel shows the error text instead.
|
|
107
|
+
|
|
108
|
+
### The render service
|
|
109
|
+
|
|
110
|
+
macOS runs Quick Look extensions in a sandbox that VTK cannot render inside, so
|
|
111
|
+
rendering happens in a launch agent instead. `scripts/install.sh` sets it up.
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
pvql service # report whether it is loaded
|
|
115
|
+
pvql service --install # (re)install and start it
|
|
116
|
+
pvql service --uninstall
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Its output goes to `~/Library/Logs/pvqld.log`.
|
|
120
|
+
|
|
121
|
+
### Files in the Desktop, Documents, and Downloads folders
|
|
122
|
+
|
|
123
|
+
macOS keeps those folders private to each program, and the render service cannot read
|
|
124
|
+
them. The Quick Look extension copies the file it was asked to preview into its own
|
|
125
|
+
container so that the service can render it anyway.
|
|
126
|
+
|
|
127
|
+
A dataset that points at neighbouring files — `.pvd`, `.vtm`, `.case`, `.foam` — needs
|
|
128
|
+
those neighbours, which the copy does not include. Keep such datasets outside those
|
|
129
|
+
three folders, or grant the render service Full Disk Access in System Settings under
|
|
130
|
+
Privacy & Security.
|
|
131
|
+
|
|
132
|
+
## Configuration
|
|
133
|
+
|
|
134
|
+
`~/Library/Application Support/PyVistaQuickLook/config.json`
|
|
135
|
+
|
|
136
|
+
| Key | Default | Effect |
|
|
137
|
+
| --- | --- | --- |
|
|
138
|
+
| `python` | set at install | Interpreter of the PyVista environment |
|
|
139
|
+
| `pyvista` | unset | Optional `pyvista` executable, for still images |
|
|
140
|
+
| `pvql` | discovered | Absolute path to the `pvql` helper |
|
|
141
|
+
| `interactive` | `true` | Show a turnable surface instead of a still image |
|
|
142
|
+
| `max_scene_points` | `2000000` | Decimate only above this many points; `0` never does |
|
|
143
|
+
| `colormap` | `'viridis'` | Colormap used to colour the surface |
|
|
144
|
+
| `warm_on_start` | `true` | Load PyVista and VTK when the render service starts |
|
|
145
|
+
| `window_size` | `[1024, 1024]` | Rendered preview size in pixels |
|
|
146
|
+
| `timeout` | `60` | Seconds before a render is abandoned |
|
|
147
|
+
| `max_file_size_mb` | `512` | Files above this size show a notice instead of a render |
|
|
148
|
+
| `background` | `null` | Background color passed to `pyvista plot` |
|
|
149
|
+
| `extra_args` | `[]` | Extra arguments appended to `pyvista plot` |
|
|
150
|
+
| `cache` | `true` | Reuse previously rendered previews |
|
|
151
|
+
| `log` | `false` | Append render activity to `pvql.log` beside the config file |
|
|
152
|
+
|
|
153
|
+
Changing `extensions` requires a reinstall, because the claimed types are baked into the
|
|
154
|
+
app bundle. Every other key takes effect on the next preview.
|
|
155
|
+
|
|
156
|
+
## Commands
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
pvql preview FILE # render and print the path of the cached PNG
|
|
160
|
+
pvql warmup # load PyVista and VTK ahead of the first preview
|
|
161
|
+
pvql warm DIR # render a directory ahead of time
|
|
162
|
+
pvql types # list claimed extensions
|
|
163
|
+
pvql doctor # check every part of the integration
|
|
164
|
+
pvql service # manage the render service
|
|
165
|
+
pvql config --init # write a config file with discovered defaults
|
|
166
|
+
pvql cache --clear # delete cached previews
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Troubleshooting
|
|
170
|
+
|
|
171
|
+
Run `pvql doctor` first; it checks the helper, the app, the extension registration, the
|
|
172
|
+
service, and a real render.
|
|
173
|
+
|
|
174
|
+
- **The panel says the service is not answering.** Run `pvql service --install`.
|
|
175
|
+
- **Nothing happens on space bar.** Confirm the type is claimed with `pvql types`, then
|
|
176
|
+
check that Finder resolves it: `mdls -name kMDItemContentType yourfile.vtu` should
|
|
177
|
+
report an `io.github.user27182.pyvista-quicklook.*` type.
|
|
178
|
+
- **Previews are stale.** `pvql cache --clear`.
|
|
179
|
+
- **A render fails.** Set `"log": true` in the config; activity is appended to
|
|
180
|
+
`pvql.log` beside it. The extension's own log is in
|
|
181
|
+
`~/Library/Containers/io.github.user27182.PyVistaQuickLook.QuickLook/Data/tmp/`.
|
|
182
|
+
|
|
183
|
+
## Development
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
uv sync --group dev
|
|
187
|
+
uv run pytest tests/ # helper tests, with coverage
|
|
188
|
+
uv run pre-commit run --all-files
|
|
189
|
+
./scripts/build.sh # compile and sign the app bundle
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
`main` is protected by a pre-commit hook, so work on a branch.
|
|
193
|
+
|
|
194
|
+
Releases are published to PyPI by CI through trusted publishing: push a `v*` tag and
|
|
195
|
+
the `publish` job uploads from the `release` environment. That requires a matching
|
|
196
|
+
pending publisher configured on PyPI for this repository and workflow.
|
|
197
|
+
|
|
198
|
+
## Uninstall
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
./scripts/uninstall.sh
|
|
202
|
+
uv tool uninstall pyvista-quicklook
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
That removes the app, the private PyVista environment, the downloaded source, and the
|
|
206
|
+
cache, leaving only the config file.
|