ad-hoc-diffractometer 0.3.1__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.
Files changed (71) hide show
  1. ad_hoc_diffractometer-0.3.1/.copyright.txt +2 -0
  2. ad_hoc_diffractometer-0.3.1/.github/dependabot.yml +11 -0
  3. ad_hoc_diffractometer-0.3.1/.github/workflows/docs.yml +225 -0
  4. ad_hoc_diffractometer-0.3.1/.github/workflows/docs_backfill.yml +191 -0
  5. ad_hoc_diffractometer-0.3.1/.github/workflows/pypi.yml +47 -0
  6. ad_hoc_diffractometer-0.3.1/.github/workflows/tests.yml +44 -0
  7. ad_hoc_diffractometer-0.3.1/.gitignore +22 -0
  8. ad_hoc_diffractometer-0.3.1/.pre-commit-config.yaml +40 -0
  9. ad_hoc_diffractometer-0.3.1/AGENTS.md +347 -0
  10. ad_hoc_diffractometer-0.3.1/CHANGES.md +177 -0
  11. ad_hoc_diffractometer-0.3.1/LICENSE +95 -0
  12. ad_hoc_diffractometer-0.3.1/PKG-INFO +36 -0
  13. ad_hoc_diffractometer-0.3.1/README.md +68 -0
  14. ad_hoc_diffractometer-0.3.1/docs/Makefile +14 -0
  15. ad_hoc_diffractometer-0.3.1/docs/make.bat +30 -0
  16. ad_hoc_diffractometer-0.3.1/docs/source/_static/switcher.json +11 -0
  17. ad_hoc_diffractometer-0.3.1/docs/source/api.rst +12 -0
  18. ad_hoc_diffractometer-0.3.1/docs/source/changes.md +4 -0
  19. ad_hoc_diffractometer-0.3.1/docs/source/conf.py +126 -0
  20. ad_hoc_diffractometer-0.3.1/docs/source/direct-lattice.md +92 -0
  21. ad_hoc_diffractometer-0.3.1/docs/source/fourcv_alignment_howto.ipynb +840 -0
  22. ad_hoc_diffractometer-0.3.1/docs/source/index.rst +36 -0
  23. ad_hoc_diffractometer-0.3.1/docs/source/install.md +42 -0
  24. ad_hoc_diffractometer-0.3.1/docs/source/problem1.md +78 -0
  25. ad_hoc_diffractometer-0.3.1/docs/source/problem1_solution.pdf +0 -0
  26. ad_hoc_diffractometer-0.3.1/docs/source/problem1_solution.tex +250 -0
  27. ad_hoc_diffractometer-0.3.1/docs/source/problem2.md +155 -0
  28. ad_hoc_diffractometer-0.3.1/docs/source/problem3.md +8 -0
  29. ad_hoc_diffractometer-0.3.1/docs/source/roadmap.md +618 -0
  30. ad_hoc_diffractometer-0.3.1/pyproject.toml +116 -0
  31. ad_hoc_diffractometer-0.3.1/src/ad_hoc_diffractometer/__init__.py +202 -0
  32. ad_hoc_diffractometer-0.3.1/src/ad_hoc_diffractometer/_version.py +24 -0
  33. ad_hoc_diffractometer-0.3.1/src/ad_hoc_diffractometer/axes.py +265 -0
  34. ad_hoc_diffractometer-0.3.1/src/ad_hoc_diffractometer/constants.py +25 -0
  35. ad_hoc_diffractometer-0.3.1/src/ad_hoc_diffractometer/display.py +164 -0
  36. ad_hoc_diffractometer-0.3.1/src/ad_hoc_diffractometer/engines.py +508 -0
  37. ad_hoc_diffractometer-0.3.1/src/ad_hoc_diffractometer/factories.py +951 -0
  38. ad_hoc_diffractometer-0.3.1/src/ad_hoc_diffractometer/forward.py +617 -0
  39. ad_hoc_diffractometer-0.3.1/src/ad_hoc_diffractometer/geometry.py +2114 -0
  40. ad_hoc_diffractometer-0.3.1/src/ad_hoc_diffractometer/lattice.py +816 -0
  41. ad_hoc_diffractometer-0.3.1/src/ad_hoc_diffractometer/mode.py +390 -0
  42. ad_hoc_diffractometer-0.3.1/src/ad_hoc_diffractometer/orientation.py +815 -0
  43. ad_hoc_diffractometer-0.3.1/src/ad_hoc_diffractometer/radiation.py +361 -0
  44. ad_hoc_diffractometer-0.3.1/src/ad_hoc_diffractometer/refinement.py +973 -0
  45. ad_hoc_diffractometer-0.3.1/src/ad_hoc_diffractometer/reflection.py +432 -0
  46. ad_hoc_diffractometer-0.3.1/src/ad_hoc_diffractometer/rotation.py +70 -0
  47. ad_hoc_diffractometer-0.3.1/src/ad_hoc_diffractometer/sample.py +280 -0
  48. ad_hoc_diffractometer-0.3.1/src/ad_hoc_diffractometer/scan.py +1035 -0
  49. ad_hoc_diffractometer-0.3.1/src/ad_hoc_diffractometer/stage.py +164 -0
  50. ad_hoc_diffractometer-0.3.1/src/ad_hoc_diffractometer/surface.py +433 -0
  51. ad_hoc_diffractometer-0.3.1/tests/__init__.py +0 -0
  52. ad_hoc_diffractometer-0.3.1/tests/conftest.py +34 -0
  53. ad_hoc_diffractometer-0.3.1/tests/helpers.py +51 -0
  54. ad_hoc_diffractometer-0.3.1/tests/test_axes.py +269 -0
  55. ad_hoc_diffractometer-0.3.1/tests/test_display.py +162 -0
  56. ad_hoc_diffractometer-0.3.1/tests/test_engines.py +441 -0
  57. ad_hoc_diffractometer-0.3.1/tests/test_factories.py +1008 -0
  58. ad_hoc_diffractometer-0.3.1/tests/test_forward.py +590 -0
  59. ad_hoc_diffractometer-0.3.1/tests/test_geometry.py +2002 -0
  60. ad_hoc_diffractometer-0.3.1/tests/test_lattice.py +978 -0
  61. ad_hoc_diffractometer-0.3.1/tests/test_mode.py +747 -0
  62. ad_hoc_diffractometer-0.3.1/tests/test_orientation.py +1378 -0
  63. ad_hoc_diffractometer-0.3.1/tests/test_radiation.py +645 -0
  64. ad_hoc_diffractometer-0.3.1/tests/test_refinement.py +734 -0
  65. ad_hoc_diffractometer-0.3.1/tests/test_reflection.py +748 -0
  66. ad_hoc_diffractometer-0.3.1/tests/test_rotation.py +100 -0
  67. ad_hoc_diffractometer-0.3.1/tests/test_sample.py +536 -0
  68. ad_hoc_diffractometer-0.3.1/tests/test_scan.py +981 -0
  69. ad_hoc_diffractometer-0.3.1/tests/test_stage.py +310 -0
  70. ad_hoc_diffractometer-0.3.1/tests/test_surface.py +638 -0
  71. ad_hoc_diffractometer-0.3.1/threading_diagnostics.md +473 -0
@@ -0,0 +1,2 @@
1
+ Copyright (c) 2026 Pete R. Jemian <prjemian+ad_hoc_diffractometer@gmail.com>
2
+ SPDX-License-Identifier: CC-BY-4.0
@@ -0,0 +1,11 @@
1
+ # Set update schedule for GitHub Actions
2
+ # https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot
3
+ # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
4
+
5
+ version: 2
6
+ updates:
7
+ - package-ecosystem: "github-actions"
8
+ directory: "/"
9
+ schedule:
10
+ # Check for updates to GitHub Actions every week
11
+ interval: "weekly"
@@ -0,0 +1,225 @@
1
+ name: Publish Sphinx Docs to GitHub Pages
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ tags:
8
+ - '*'
9
+ pull_request:
10
+ branches:
11
+ - main
12
+ workflow_dispatch:
13
+ inputs:
14
+ deploy:
15
+ description: 'Deploy documentation'
16
+ type: boolean
17
+ required: true
18
+ default: false
19
+
20
+ concurrency:
21
+ group: ${{ github.workflow }}-${{ github.ref }}
22
+ cancel-in-progress: true
23
+
24
+ permissions:
25
+ contents: write
26
+
27
+ jobs:
28
+
29
+ docs:
30
+ name: Build and publish documentation
31
+ runs-on: ubuntu-latest
32
+
33
+ steps:
34
+
35
+ - name: Checkout
36
+ uses: actions/checkout@v6
37
+ with:
38
+ fetch-depth: 0 # full history so hatch-vcs can read git tags
39
+
40
+ - name: Set up Python
41
+ uses: actions/setup-python@v6
42
+ with:
43
+ python-version: "3.12"
44
+ cache: pip
45
+
46
+ - name: Install pandoc
47
+ run: |
48
+ sudo apt-get update
49
+ sudo apt-get install -y pandoc
50
+
51
+ - name: Install package with doc dependencies
52
+ run: pip install -e .[doc]
53
+
54
+ - name: Determine DOC_VERSION
55
+ run: |
56
+ if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
57
+ VERSION="${GITHUB_REF#refs/tags/}"
58
+ else
59
+ VERSION="latest"
60
+ fi
61
+ echo "DOC_VERSION=${VERSION}" >> "${GITHUB_ENV}"
62
+ echo "Publishing docs as: ${VERSION}"
63
+
64
+ - name: Build Sphinx documentation
65
+ # Note: -W (warnings-as-errors) is intentionally omitted here.
66
+ # Pre-existing docstring formatting issues produce AutoAPI warnings
67
+ # that are tracked separately and will be fixed in Phase 2 content work.
68
+ run: |
69
+ python3 -m sphinx -b html docs/source docs/build/html
70
+
71
+ - name: Upload docs as workflow artifact
72
+ uses: actions/upload-artifact@v7
73
+ with:
74
+ name: docs-${{ env.DOC_VERSION }}
75
+ path: docs/build/html
76
+
77
+ - name: Deploy to gh-pages — latest/ (main push)
78
+ uses: peaceiris/actions-gh-pages@v4
79
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
80
+ with:
81
+ github_token: ${{ secrets.GITHUB_TOKEN }}
82
+ publish_branch: gh-pages
83
+ publish_dir: docs/build/html
84
+ destination_dir: latest
85
+ keep_files: true
86
+
87
+ - name: Deploy to gh-pages — <version>/ (tag push)
88
+ uses: peaceiris/actions-gh-pages@v4
89
+ if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
90
+ with:
91
+ github_token: ${{ secrets.GITHUB_TOKEN }}
92
+ publish_branch: gh-pages
93
+ publish_dir: docs/build/html
94
+ destination_dir: ${{ env.DOC_VERSION }}
95
+ keep_files: true
96
+
97
+ - name: Update switcher.json on tag push
98
+ if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
99
+ run: |
100
+ set -euo pipefail
101
+ VERSION="${DOC_VERSION}"
102
+
103
+ # Clone gh-pages to update switcher.json
104
+ git clone --branch gh-pages --depth 1 \
105
+ "https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git" \
106
+ gh-pages-clone
107
+
108
+ SWITCHER="gh-pages-clone/latest/_static/switcher.json"
109
+
110
+ # If switcher.json doesn't exist yet, bootstrap from source
111
+ if [ ! -f "${SWITCHER}" ]; then
112
+ mkdir -p "$(dirname ${SWITCHER})"
113
+ cp docs/source/_static/switcher.json "${SWITCHER}"
114
+ fi
115
+
116
+ # Update switcher.json.
117
+ # Pre-releases (rcN, aN, bN) appear in the switcher but do not steal
118
+ # "preferred" from the current stable release.
119
+ # Stable releases also prune all pre-release entries for the same
120
+ # base version (e.g. finalising 0.4.1 removes 0.4.1rc1, 0.4.1a1, …).
121
+ python3 - <<'PYEOF'
122
+ import json, os, re
123
+
124
+ version = os.environ["VERSION"]
125
+ switcher_path = os.environ["SWITCHER"]
126
+ base_url = "https://prjemian.github.io/ad_hoc_diffractometer"
127
+
128
+ is_prerelease = bool(re.search(r'(a|b|rc)\d+$', version))
129
+
130
+ with open(switcher_path) as f:
131
+ entries = json.load(f)
132
+
133
+ versions = [e["version"] for e in entries]
134
+ insert_pos = next(
135
+ (i + 1 for i, e in enumerate(entries) if e.get("version") == "latest"),
136
+ 1,
137
+ )
138
+
139
+ if not is_prerelease:
140
+ # Remove all pre-release entries for this base version.
141
+ prerelease_pat = re.compile(r'^' + re.escape(version) + r'(a|b|rc)\d+$')
142
+ pruned = [e["version"] for e in entries if prerelease_pat.match(e["version"])]
143
+ entries = [e for e in entries if not prerelease_pat.match(e["version"])]
144
+ for v in pruned:
145
+ print(f"Removed pre-release {v} from switcher.json")
146
+ # Recalculate insert position after pruning.
147
+ insert_pos = next(
148
+ (i + 1 for i, e in enumerate(entries) if e.get("version") == "latest"),
149
+ 1,
150
+ )
151
+ versions = [e["version"] for e in entries]
152
+ # Clear preferred everywhere, then mark this stable version.
153
+ for e in entries:
154
+ e.pop("preferred", None)
155
+ if version in versions:
156
+ for e in entries:
157
+ if e["version"] == version:
158
+ e["preferred"] = True
159
+ print(f"{version} already present; marked preferred")
160
+ else:
161
+ new_entry = {"version": version, "url": f"{base_url}/{version}/", "preferred": True}
162
+ entries.insert(insert_pos, new_entry)
163
+ print(f"Added {version} to switcher.json and marked preferred")
164
+ else:
165
+ # Pre-release: add without touching preferred.
166
+ if version in versions:
167
+ print(f"{version} already present (pre-release; preferred unchanged)")
168
+ else:
169
+ new_entry = {"version": version, "url": f"{base_url}/{version}/"}
170
+ entries.insert(insert_pos, new_entry)
171
+ print(f"Added pre-release {version} to switcher.json (preferred unchanged)")
172
+
173
+ with open(switcher_path, "w") as f:
174
+ json.dump(entries, f, indent=4)
175
+ PYEOF
176
+ env:
177
+ SWITCHER: gh-pages-clone/latest/_static/switcher.json
178
+ VERSION: ${{ env.DOC_VERSION }}
179
+
180
+ - name: Remove pre-release doc directories from gh-pages on stable tag
181
+ if: >
182
+ github.event_name == 'push' &&
183
+ startsWith(github.ref, 'refs/tags/') &&
184
+ !contains(env.DOC_VERSION, 'a') &&
185
+ !contains(env.DOC_VERSION, 'b') &&
186
+ !contains(env.DOC_VERSION, 'rc')
187
+ run: |
188
+ set -euo pipefail
189
+ VERSION="${DOC_VERSION}"
190
+
191
+ # Delete gh-pages/<base>rcN, <base>aN, <base>bN directories if present.
192
+ PRUNED=()
193
+ for dir in gh-pages-clone/${VERSION}{a,b,rc}*/; do
194
+ [ -d "${dir}" ] || continue
195
+ rm -rf "${dir}"
196
+ PRUNED+=("${dir}")
197
+ echo "Removed directory: ${dir}"
198
+ done
199
+
200
+ if [[ ${#PRUNED[@]} -eq 0 ]]; then
201
+ echo "No pre-release directories found for ${VERSION}."
202
+ fi
203
+
204
+ - name: Commit switcher.json and pruned directories to gh-pages
205
+ if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
206
+ run: |
207
+ cd gh-pages-clone
208
+ git config user.name "github-actions[bot]"
209
+ git config user.email "github-actions[bot]@users.noreply.github.com"
210
+ git add -A
211
+ git diff --cached --quiet || git commit -m "ci: release ${DOC_VERSION}: update switcher.json, prune pre-release docs"
212
+ # Pull with rebase before pushing to avoid "fetch first" rejection
213
+ # when the earlier gh-pages deploy step has already pushed to the branch.
214
+ git pull --rebase origin gh-pages
215
+ git push
216
+
217
+ - name: Deploy on manual trigger
218
+ uses: peaceiris/actions-gh-pages@v4
219
+ if: github.event_name == 'workflow_dispatch' && github.event.inputs.deploy == 'true'
220
+ with:
221
+ github_token: ${{ secrets.GITHUB_TOKEN }}
222
+ publish_branch: gh-pages
223
+ publish_dir: docs/build/html
224
+ destination_dir: latest
225
+ keep_files: true
@@ -0,0 +1,191 @@
1
+ name: Backfill Docs for a Tagged Version
2
+
3
+ # Use this workflow to publish docs for a tag that was released before
4
+ # versioned docs were introduced. Run manually from the Actions tab.
5
+ #
6
+ # Usage:
7
+ # 1. Go to Actions -> "Backfill Docs for a Tagged Version"
8
+ # 2. Click "Run workflow"
9
+ # 3. Enter the tag (e.g. "v0.2.0") in the input field
10
+ # 4. Click "Run workflow"
11
+
12
+ on:
13
+ workflow_dispatch:
14
+ inputs:
15
+ tag:
16
+ description: 'Tag to build and publish (e.g. v0.2.0)'
17
+ required: true
18
+ type: string
19
+
20
+ permissions:
21
+ contents: write
22
+
23
+ jobs:
24
+
25
+ backfill:
26
+ name: Backfill docs for tag ${{ github.event.inputs.tag }}
27
+ runs-on: ubuntu-latest
28
+
29
+ steps:
30
+
31
+ - name: Deploy Information
32
+ run: |
33
+ echo "Building and publishing docs for tag: ${{ github.event.inputs.tag }}"
34
+
35
+ - name: Make Temporary Directory
36
+ run: |
37
+ echo "TMP_DIR=$(mktemp -d)" >> "${GITHUB_ENV}"
38
+ echo "DOC_VERSION=${{ github.event.inputs.tag }}" >> "${GITHUB_ENV}"
39
+
40
+ - name: Install pandoc
41
+ run: |
42
+ set -vxeuo pipefail
43
+ sudo apt-get update && sudo apt-get -y install pandoc
44
+
45
+ - name: Checkout tag
46
+ uses: actions/checkout@v6
47
+ with:
48
+ ref: ${{ github.event.inputs.tag }}
49
+ fetch-depth: 0
50
+
51
+ - name: Set up Python
52
+ uses: actions/setup-python@v6
53
+ with:
54
+ python-version: "3.12"
55
+ cache: pip
56
+
57
+ - name: Install package and doc requirements
58
+ run: pip install -e .[doc]
59
+
60
+ - name: Build docs
61
+ run: |
62
+ HTML_DIR="${TMP_DIR}/build/${DOC_VERSION}"
63
+ echo "HTML_DIR=${HTML_DIR}" >> "${GITHUB_ENV}"
64
+ python3 -m sphinx -b html docs/source "${HTML_DIR}"
65
+
66
+ - name: Upload artifact
67
+ uses: actions/upload-artifact@v7
68
+ with:
69
+ name: docs-${{ env.DOC_VERSION }}
70
+ path: ${{ env.HTML_DIR }}
71
+
72
+ - name: Deploy to gh-pages/<version>/
73
+ uses: peaceiris/actions-gh-pages@v4
74
+ with:
75
+ github_token: ${{ secrets.GITHUB_TOKEN }}
76
+ publish_branch: gh-pages
77
+ publish_dir: ${{ env.HTML_DIR }}
78
+ destination_dir: ${{ env.DOC_VERSION }}
79
+ keep_files: true
80
+
81
+ - name: Update switcher.json on gh-pages
82
+ run: |
83
+ set -euo pipefail
84
+ VERSION="${DOC_VERSION}"
85
+
86
+ git clone --branch gh-pages --depth 1 \
87
+ "https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git" \
88
+ gh-pages-clone
89
+
90
+ SWITCHER="gh-pages-clone/latest/_static/switcher.json"
91
+
92
+ if [ ! -f "${SWITCHER}" ]; then
93
+ echo "switcher.json not found at ${SWITCHER} — skipping update"
94
+ exit 0
95
+ fi
96
+
97
+ # Update switcher.json.
98
+ # Pre-releases (rcN, aN, bN) appear in the switcher but do not steal
99
+ # "preferred" from the current stable release.
100
+ # Stable releases also prune all pre-release entries for the same
101
+ # base version (e.g. finalising 0.4.1 removes 0.4.1rc1, 0.4.1a1, …).
102
+ python3 - <<'PYEOF'
103
+ import json, os, re
104
+
105
+ version = os.environ["VERSION"]
106
+ switcher_path = os.environ["SWITCHER"]
107
+ base_url = "https://prjemian.github.io/ad_hoc_diffractometer"
108
+
109
+ is_prerelease = bool(re.search(r'(a|b|rc)\d+$', version))
110
+
111
+ with open(switcher_path) as f:
112
+ entries = json.load(f)
113
+
114
+ versions = [e["version"] for e in entries]
115
+ insert_pos = next(
116
+ (i + 1 for i, e in enumerate(entries) if e.get("version") == "latest"),
117
+ 1,
118
+ )
119
+
120
+ if not is_prerelease:
121
+ # Remove all pre-release entries for this base version.
122
+ prerelease_pat = re.compile(r'^' + re.escape(version) + r'(a|b|rc)\d+$')
123
+ pruned = [e["version"] for e in entries if prerelease_pat.match(e["version"])]
124
+ entries = [e for e in entries if not prerelease_pat.match(e["version"])]
125
+ for v in pruned:
126
+ print(f"Removed pre-release {v} from switcher.json")
127
+ # Recalculate insert position after pruning.
128
+ insert_pos = next(
129
+ (i + 1 for i, e in enumerate(entries) if e.get("version") == "latest"),
130
+ 1,
131
+ )
132
+ versions = [e["version"] for e in entries]
133
+ # Clear preferred everywhere, then mark this stable version.
134
+ for e in entries:
135
+ e.pop("preferred", None)
136
+ if version in versions:
137
+ for e in entries:
138
+ if e["version"] == version:
139
+ e["preferred"] = True
140
+ print(f"{version} already present; marked preferred")
141
+ else:
142
+ new_entry = {"version": version, "url": f"{base_url}/{version}/", "preferred": True}
143
+ entries.insert(insert_pos, new_entry)
144
+ print(f"Added {version} and marked preferred")
145
+ else:
146
+ # Pre-release: add without touching preferred.
147
+ if version in versions:
148
+ print(f"{version} already present (pre-release; preferred unchanged)")
149
+ else:
150
+ new_entry = {"version": version, "url": f"{base_url}/{version}/"}
151
+ entries.insert(insert_pos, new_entry)
152
+ print(f"Added pre-release {version} (preferred unchanged)")
153
+
154
+ with open(switcher_path, "w") as f:
155
+ json.dump(entries, f, indent=4)
156
+ PYEOF
157
+ env:
158
+ SWITCHER: gh-pages-clone/latest/_static/switcher.json
159
+ VERSION: ${{ env.DOC_VERSION }}
160
+
161
+ - name: Remove pre-release doc directories from gh-pages on stable tag
162
+ if: >
163
+ !contains(env.DOC_VERSION, 'a') &&
164
+ !contains(env.DOC_VERSION, 'b') &&
165
+ !contains(env.DOC_VERSION, 'rc')
166
+ run: |
167
+ set -euo pipefail
168
+ VERSION="${DOC_VERSION}"
169
+
170
+ # Delete gh-pages/<base>rcN, <base>aN, <base>bN directories if present.
171
+ PRUNED=()
172
+ for dir in gh-pages-clone/${VERSION}{a,b,rc}*/; do
173
+ [ -d "${dir}" ] || continue
174
+ rm -rf "${dir}"
175
+ PRUNED+=("${dir}")
176
+ echo "Removed directory: ${dir}"
177
+ done
178
+
179
+ if [[ ${#PRUNED[@]} -eq 0 ]]; then
180
+ echo "No pre-release directories found for ${VERSION}."
181
+ fi
182
+
183
+ - name: Commit switcher.json and pruned directories to gh-pages
184
+ run: |
185
+ cd gh-pages-clone
186
+ git config user.name "github-actions[bot]"
187
+ git config user.email "github-actions[bot]@users.noreply.github.com"
188
+ git add -A
189
+ git diff --cached --quiet || git commit -m "ci: release ${DOC_VERSION}: update switcher.json, prune pre-release docs (backfill)"
190
+ git pull --rebase origin gh-pages
191
+ git push
@@ -0,0 +1,47 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ tags:
8
+ - '*'
9
+ workflow_dispatch:
10
+
11
+ permissions:
12
+ id-token: write
13
+
14
+ concurrency:
15
+ group: ${{ github.workflow }}-${{ github.ref }}
16
+ cancel-in-progress: true
17
+
18
+ jobs:
19
+
20
+ build-pypi:
21
+ name: Build and publish to PyPI
22
+ runs-on: ubuntu-latest
23
+
24
+ steps:
25
+ - uses: actions/checkout@v6
26
+ with:
27
+ fetch-depth: 0
28
+
29
+ - name: Set up Python
30
+ uses: actions/setup-python@v6
31
+ with:
32
+ python-version: "3.12"
33
+
34
+ - name: Install build tools
35
+ run: pip install --upgrade build twine
36
+
37
+ - name: Build sdist and wheel
38
+ run: python -m build --sdist --wheel --outdir dist/ .
39
+
40
+ - name: Check package metadata
41
+ run: twine check dist/*
42
+
43
+ - name: Publish to PyPI
44
+ if: startsWith(github.ref, 'refs/tags/')
45
+ uses: pypa/gh-action-pypi-publish@release/v1
46
+ with:
47
+ verbose: true
@@ -0,0 +1,44 @@
1
+ name: Unit Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ concurrency:
10
+ group: ${{ github.workflow }}-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ jobs:
14
+ test:
15
+ name: Python ${{ matrix.python-version }}
16
+ runs-on: ubuntu-latest
17
+
18
+ strategy:
19
+ fail-fast: false
20
+ matrix:
21
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
22
+ include:
23
+ # 3.14 is pre-release; run it for early warning but don't fail CI
24
+ - python-version: "3.14-dev"
25
+ continue-on-error: true
26
+
27
+ continue-on-error: ${{ matrix.continue-on-error == true }}
28
+
29
+ steps:
30
+ - uses: actions/checkout@v6
31
+ with:
32
+ fetch-depth: 0 # full history so hatch-vcs can read git tags
33
+
34
+ - name: Set up Python ${{ matrix.python-version }}
35
+ uses: actions/setup-python@v6
36
+ with:
37
+ python-version: ${{ matrix.python-version }}
38
+ cache: pip
39
+
40
+ - name: Install package with dev dependencies
41
+ run: pip install -e .[dev]
42
+
43
+ - name: Run tests
44
+ run: python -m pytest -v
@@ -0,0 +1,22 @@
1
+ references/
2
+ src/ad_hoc_diffractometer/_version.py
3
+ docs/build/
4
+ docs/source/autoapi/
5
+ .coverage
6
+ htmlcov/
7
+ .pytest_cache/
8
+ __pycache__/
9
+ *.py[cod]
10
+ *.egg-info/
11
+ dist/
12
+ build/
13
+ *.egg
14
+ *.log
15
+ *.bak
16
+ *.swp
17
+ .DS_Store
18
+ .idea/
19
+ .vscode/
20
+ .loglogin
21
+ dev_*
22
+ dev_*/
@@ -0,0 +1,40 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v5.0.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ - id: check-yaml
8
+ - id: check-toml
9
+ - id: check-merge-conflict
10
+ - id: debug-statements
11
+
12
+ - repo: https://github.com/Lucas-C/pre-commit-hooks
13
+ rev: v1.5.5
14
+ hooks:
15
+ - id: insert-license
16
+ name: insert-license (src)
17
+ files: ^src/ad_hoc_diffractometer/(?!_version).*\.py$
18
+ args:
19
+ - --license-filepath=.copyright.txt
20
+ - --comment-style=#
21
+ - --no-extra-eol
22
+ - id: insert-license
23
+ name: insert-license (tests)
24
+ files: ^tests/test_.*\.py$
25
+ args:
26
+ - --license-filepath=.copyright.txt
27
+ - --comment-style=#
28
+ - --no-extra-eol
29
+
30
+ - repo: https://github.com/PyCQA/isort
31
+ rev: 5.13.2
32
+ hooks:
33
+ - id: isort
34
+
35
+ - repo: https://github.com/astral-sh/ruff-pre-commit
36
+ rev: v0.9.10
37
+ hooks:
38
+ - id: ruff
39
+ args: [--fix]
40
+ - id: ruff-format