impregcalc 0.1.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.
- impregcalc-0.1.0/.github/ISSUE_TEMPLATE/bug.yml +27 -0
- impregcalc-0.1.0/.github/ISSUE_TEMPLATE/dataset.yml +27 -0
- impregcalc-0.1.0/.github/ISSUE_TEMPLATE/feature.yml +19 -0
- impregcalc-0.1.0/.github/ISSUE_TEMPLATE/macos-gui.yml +53 -0
- impregcalc-0.1.0/.github/ISSUE_TEMPLATE/scientific-result.yml +26 -0
- impregcalc-0.1.0/.github/dependabot.yml +13 -0
- impregcalc-0.1.0/.github/workflows/ci.yml +173 -0
- impregcalc-0.1.0/.github/workflows/macos.yml +95 -0
- impregcalc-0.1.0/.github/workflows/publish.yml +69 -0
- impregcalc-0.1.0/.gitignore +13 -0
- impregcalc-0.1.0/CHANGELOG.md +16 -0
- impregcalc-0.1.0/CITATION.cff +16 -0
- impregcalc-0.1.0/CONTRIBUTING.md +41 -0
- impregcalc-0.1.0/LICENSE +22 -0
- impregcalc-0.1.0/PKG-INFO +212 -0
- impregcalc-0.1.0/README.md +148 -0
- impregcalc-0.1.0/SECURITY.md +8 -0
- impregcalc-0.1.0/assets/social-preview.png +0 -0
- impregcalc-0.1.0/docs/ci-security.md +31 -0
- impregcalc-0.1.0/docs/input-schema.md +29 -0
- impregcalc-0.1.0/docs/macos.md +63 -0
- impregcalc-0.1.0/docs/naming-audit.md +40 -0
- impregcalc-0.1.0/docs/scientific-basis.md +146 -0
- impregcalc-0.1.0/docs/validation.md +47 -0
- impregcalc-0.1.0/examples/co_ru_iwi.json +35 -0
- impregcalc-0.1.0/examples/nickel_oxide_wet.json +21 -0
- impregcalc-0.1.0/pyproject.toml +87 -0
- impregcalc-0.1.0/src/impregcalc/__init__.py +35 -0
- impregcalc-0.1.0/src/impregcalc/application/__init__.py +1 -0
- impregcalc-0.1.0/src/impregcalc/application/service.py +115 -0
- impregcalc-0.1.0/src/impregcalc/cli/__init__.py +5 -0
- impregcalc-0.1.0/src/impregcalc/cli/__main__.py +3 -0
- impregcalc-0.1.0/src/impregcalc/cli/main.py +90 -0
- impregcalc-0.1.0/src/impregcalc/core/__init__.py +1 -0
- impregcalc-0.1.0/src/impregcalc/core/calculator.py +307 -0
- impregcalc-0.1.0/src/impregcalc/core/errors.py +13 -0
- impregcalc-0.1.0/src/impregcalc/core/formula.py +201 -0
- impregcalc-0.1.0/src/impregcalc/core/models.py +224 -0
- impregcalc-0.1.0/src/impregcalc/gui/__init__.py +12 -0
- impregcalc-0.1.0/src/impregcalc/gui/__main__.py +3 -0
- impregcalc-0.1.0/src/impregcalc/gui/app.py +198 -0
- impregcalc-0.1.0/src/impregcalc/io/__init__.py +5 -0
- impregcalc-0.1.0/src/impregcalc/io/export.py +180 -0
- impregcalc-0.1.0/src/impregcalc/plotting/__init__.py +5 -0
- impregcalc-0.1.0/src/impregcalc/plotting/recipe.py +46 -0
- impregcalc-0.1.0/src/impregcalc/py.typed +1 -0
- impregcalc-0.1.0/tests/gui/test_gui_import.py +21 -0
- impregcalc-0.1.0/tests/gui_widget_smoke.py +24 -0
- impregcalc-0.1.0/tests/integration/test_cli.py +43 -0
- impregcalc-0.1.0/tests/integration/test_project_contracts.py +51 -0
- impregcalc-0.1.0/tests/integration/test_service_and_export.py +65 -0
- impregcalc-0.1.0/tests/macos/test_macos_gui_lifecycle.py +23 -0
- impregcalc-0.1.0/tests/unit/test_calculator.py +200 -0
- impregcalc-0.1.0/tests/unit/test_formula.py +36 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Report reproducible software behavior that is not a scientific-definition question.
|
|
3
|
+
title: "[Bug]: "
|
|
4
|
+
labels: [bug]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: "Do not upload confidential or unpublished research data to this public issue."
|
|
9
|
+
- type: input
|
|
10
|
+
id: version
|
|
11
|
+
attributes:
|
|
12
|
+
label: ImpregCalc version
|
|
13
|
+
validations:
|
|
14
|
+
required: true
|
|
15
|
+
- type: textarea
|
|
16
|
+
id: reproduce
|
|
17
|
+
attributes:
|
|
18
|
+
label: Minimal reproduction and full error output
|
|
19
|
+
validations:
|
|
20
|
+
required: true
|
|
21
|
+
- type: textarea
|
|
22
|
+
id: expected
|
|
23
|
+
attributes:
|
|
24
|
+
label: Expected behavior
|
|
25
|
+
validations:
|
|
26
|
+
required: true
|
|
27
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: Real dataset compatibility
|
|
2
|
+
description: Propose a public catalyst-preparation record for validation or compatibility.
|
|
3
|
+
title: "[Dataset]: "
|
|
4
|
+
labels: [dataset]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: "Only public, licensed data. Never attach unpublished or confidential laboratory records."
|
|
9
|
+
- type: input
|
|
10
|
+
id: doi
|
|
11
|
+
attributes:
|
|
12
|
+
label: DOI or stable public URL
|
|
13
|
+
validations:
|
|
14
|
+
required: true
|
|
15
|
+
- type: input
|
|
16
|
+
id: license
|
|
17
|
+
attributes:
|
|
18
|
+
label: Dataset license
|
|
19
|
+
validations:
|
|
20
|
+
required: true
|
|
21
|
+
- type: textarea
|
|
22
|
+
id: scope
|
|
23
|
+
attributes:
|
|
24
|
+
label: Files, checksum, and proposed validation scope
|
|
25
|
+
validations:
|
|
26
|
+
required: true
|
|
27
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Propose a focused preparation workflow or usability improvement.
|
|
3
|
+
title: "[Feature]: "
|
|
4
|
+
labels: [enhancement]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: "Do not include confidential research data. Scientific features need definitions and references."
|
|
9
|
+
- type: textarea
|
|
10
|
+
id: workflow
|
|
11
|
+
attributes:
|
|
12
|
+
label: Research workflow and current limitation
|
|
13
|
+
validations:
|
|
14
|
+
required: true
|
|
15
|
+
- type: textarea
|
|
16
|
+
id: science
|
|
17
|
+
attributes:
|
|
18
|
+
label: Scientific definition, validity range, and reference
|
|
19
|
+
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: macOS or GUI issue
|
|
2
|
+
description: Report installation, Tkinter, window lifecycle, or backend behavior on macOS.
|
|
3
|
+
title: "[macOS/GUI]: "
|
|
4
|
+
labels: [macos, gui]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: "Do not post confidential data. Remove paths or environment values that reveal secrets."
|
|
9
|
+
- type: input
|
|
10
|
+
id: macos
|
|
11
|
+
attributes:
|
|
12
|
+
label: macOS version
|
|
13
|
+
validations:
|
|
14
|
+
required: true
|
|
15
|
+
- type: dropdown
|
|
16
|
+
id: architecture
|
|
17
|
+
attributes:
|
|
18
|
+
label: Architecture
|
|
19
|
+
options: [Apple Silicon, Intel]
|
|
20
|
+
validations:
|
|
21
|
+
required: true
|
|
22
|
+
- type: input
|
|
23
|
+
id: python
|
|
24
|
+
attributes:
|
|
25
|
+
label: Python version
|
|
26
|
+
validations:
|
|
27
|
+
required: true
|
|
28
|
+
- type: input
|
|
29
|
+
id: package
|
|
30
|
+
attributes:
|
|
31
|
+
label: ImpregCalc version
|
|
32
|
+
validations:
|
|
33
|
+
required: true
|
|
34
|
+
- type: input
|
|
35
|
+
id: gui
|
|
36
|
+
attributes:
|
|
37
|
+
label: Tk/Tcl version
|
|
38
|
+
description: Run `python -c "import tkinter; print(tkinter.TkVersion)"`.
|
|
39
|
+
validations:
|
|
40
|
+
required: true
|
|
41
|
+
- type: input
|
|
42
|
+
id: install
|
|
43
|
+
attributes:
|
|
44
|
+
label: Installation method
|
|
45
|
+
validations:
|
|
46
|
+
required: true
|
|
47
|
+
- type: textarea
|
|
48
|
+
id: traceback
|
|
49
|
+
attributes:
|
|
50
|
+
label: Full traceback or terminal output
|
|
51
|
+
validations:
|
|
52
|
+
required: true
|
|
53
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Scientific result question
|
|
2
|
+
description: Ask about an equation, convention, unit, assumption, or numerical result.
|
|
3
|
+
title: "[Science]: "
|
|
4
|
+
labels: [scientific-question]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: "Use a minimal non-confidential example. Do not post unpublished or proprietary data."
|
|
9
|
+
- type: textarea
|
|
10
|
+
id: definition
|
|
11
|
+
attributes:
|
|
12
|
+
label: Loading definition, units, and assumptions
|
|
13
|
+
description: State target quantity and denominator explicitly.
|
|
14
|
+
validations:
|
|
15
|
+
required: true
|
|
16
|
+
- type: textarea
|
|
17
|
+
id: calculation
|
|
18
|
+
attributes:
|
|
19
|
+
label: Input and observed result
|
|
20
|
+
validations:
|
|
21
|
+
required: true
|
|
22
|
+
- type: input
|
|
23
|
+
id: reference
|
|
24
|
+
attributes:
|
|
25
|
+
label: Relevant publication or reference
|
|
26
|
+
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
name: DGX CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: impregcalc-dgx-${{ github.event.pull_request.number || github.ref }}
|
|
15
|
+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
required:
|
|
19
|
+
name: DGX ARM64 / required
|
|
20
|
+
# Persistent research hardware may only execute trusted owner-authored code.
|
|
21
|
+
if: >-
|
|
22
|
+
github.event_name != 'pull_request' ||
|
|
23
|
+
(github.actor == github.repository_owner &&
|
|
24
|
+
github.event.pull_request.head.repo.full_name == github.repository)
|
|
25
|
+
runs-on: [self-hosted, Linux, ARM64, dgx-spark]
|
|
26
|
+
timeout-minutes: 60
|
|
27
|
+
env:
|
|
28
|
+
PIP_NO_CACHE_DIR: "1"
|
|
29
|
+
MPLBACKEND: Agg
|
|
30
|
+
IMPREGCALC_CI_VENV: impregcalc-ci-${{ github.run_id }}-${{ github.run_attempt }}
|
|
31
|
+
IMPREGCALC_WHEEL_VENV: impregcalc-wheel-${{ github.run_id }}-${{ github.run_attempt }}
|
|
32
|
+
IMPREGCALC_CI_OUTPUT: impregcalc-output-${{ github.run_id }}-${{ github.run_attempt }}
|
|
33
|
+
steps:
|
|
34
|
+
- name: Check out source
|
|
35
|
+
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
|
36
|
+
with:
|
|
37
|
+
clean: true
|
|
38
|
+
fetch-depth: 0
|
|
39
|
+
persist-credentials: false
|
|
40
|
+
- name: Set up Python
|
|
41
|
+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
42
|
+
with:
|
|
43
|
+
python-version: "3.13"
|
|
44
|
+
- name: Configure validated shared Tk and Xvfb runtime
|
|
45
|
+
env:
|
|
46
|
+
IMPREGCALC_GUI_RUNTIME: /opt/catalysttwin-actions/shared-gui-runtime
|
|
47
|
+
run: |
|
|
48
|
+
set -eu
|
|
49
|
+
runtime="$IMPREGCALC_GUI_RUNTIME"
|
|
50
|
+
bin_dir="$runtime/usr/bin"
|
|
51
|
+
lib_dir="$runtime/usr/lib/aarch64-linux-gnu"
|
|
52
|
+
tk_dir="$runtime/usr/share/tcltk/tk8.6"
|
|
53
|
+
test -d "$bin_dir"
|
|
54
|
+
test -d "$lib_dir"
|
|
55
|
+
test -d "$tk_dir"
|
|
56
|
+
export PATH="$bin_dir:$PATH"
|
|
57
|
+
export LD_LIBRARY_PATH="$lib_dir${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
|
|
58
|
+
export TK_LIBRARY="$tk_dir"
|
|
59
|
+
printf '%s\n' "$bin_dir" >> "$GITHUB_PATH"
|
|
60
|
+
{
|
|
61
|
+
printf 'LD_LIBRARY_PATH=%s\n' "$LD_LIBRARY_PATH"
|
|
62
|
+
printf 'TK_LIBRARY=%s\n' "$TK_LIBRARY"
|
|
63
|
+
} >> "$GITHUB_ENV"
|
|
64
|
+
command -v Xvfb
|
|
65
|
+
command -v xvfb-run
|
|
66
|
+
python -c 'import tkinter; print(tkinter.TkVersion)'
|
|
67
|
+
- name: Create isolated environments
|
|
68
|
+
run: |
|
|
69
|
+
python -m venv "$RUNNER_TEMP/$IMPREGCALC_CI_VENV"
|
|
70
|
+
python -m venv "$RUNNER_TEMP/$IMPREGCALC_WHEEL_VENV"
|
|
71
|
+
mkdir -p "$RUNNER_TEMP/$IMPREGCALC_CI_OUTPUT"
|
|
72
|
+
- name: Install project and development dependencies
|
|
73
|
+
run: |
|
|
74
|
+
"$RUNNER_TEMP/$IMPREGCALC_CI_VENV/bin/python" -m pip install --upgrade pip
|
|
75
|
+
"$RUNNER_TEMP/$IMPREGCALC_CI_VENV/bin/python" -m pip install -e ".[dev,plot]"
|
|
76
|
+
"$RUNNER_TEMP/$IMPREGCALC_CI_VENV/bin/python" -m pip check
|
|
77
|
+
- name: Check formatting
|
|
78
|
+
run: |
|
|
79
|
+
"$RUNNER_TEMP/$IMPREGCALC_CI_VENV/bin/python" -m ruff format --check .
|
|
80
|
+
- name: Lint
|
|
81
|
+
run: |
|
|
82
|
+
"$RUNNER_TEMP/$IMPREGCALC_CI_VENV/bin/python" -m ruff check .
|
|
83
|
+
- name: Type check
|
|
84
|
+
run: |
|
|
85
|
+
"$RUNNER_TEMP/$IMPREGCALC_CI_VENV/bin/python" -m mypy src
|
|
86
|
+
- name: Unit, scientific, integration, and import-isolation tests
|
|
87
|
+
run: |
|
|
88
|
+
"$RUNNER_TEMP/$IMPREGCALC_CI_VENV/bin/python" -m pytest
|
|
89
|
+
- name: CLI and example workflow
|
|
90
|
+
run: |
|
|
91
|
+
py="$RUNNER_TEMP/$IMPREGCALC_CI_VENV/bin/python"
|
|
92
|
+
"$py" -m impregcalc.cli formula 'Co(NO3)2·6H2O'
|
|
93
|
+
"$py" -m impregcalc.cli validate examples/co_ru_iwi.json
|
|
94
|
+
"$py" -m impregcalc.cli calculate examples/co_ru_iwi.json \
|
|
95
|
+
--output "$RUNNER_TEMP/$IMPREGCALC_CI_OUTPUT/recipe.xlsx" \
|
|
96
|
+
--plot "$RUNNER_TEMP/$IMPREGCALC_CI_OUTPUT/recipe.svg"
|
|
97
|
+
test -s "$RUNNER_TEMP/$IMPREGCALC_CI_OUTPUT/recipe.xlsx"
|
|
98
|
+
test -s "$RUNNER_TEMP/$IMPREGCALC_CI_OUTPUT/recipe.svg"
|
|
99
|
+
- name: Wired GUI calculation, export, close, and exit
|
|
100
|
+
run: |
|
|
101
|
+
xvfb-run -a "$RUNNER_TEMP/$IMPREGCALC_CI_VENV/bin/python" \
|
|
102
|
+
tests/gui_widget_smoke.py \
|
|
103
|
+
"$RUNNER_TEMP/$IMPREGCALC_CI_OUTPUT/gui-recipe.md"
|
|
104
|
+
test -s "$RUNNER_TEMP/$IMPREGCALC_CI_OUTPUT/gui-recipe.md"
|
|
105
|
+
- name: Build and validate distributions
|
|
106
|
+
run: |
|
|
107
|
+
py="$RUNNER_TEMP/$IMPREGCALC_CI_VENV/bin/python"
|
|
108
|
+
"$py" -m build
|
|
109
|
+
"$py" -m twine check dist/*
|
|
110
|
+
- name: Verify clean wheel without GUI or plotting dependencies
|
|
111
|
+
run: |
|
|
112
|
+
py="$RUNNER_TEMP/$IMPREGCALC_WHEEL_VENV/bin/python"
|
|
113
|
+
"$py" -m pip install --upgrade pip
|
|
114
|
+
"$py" -m pip install dist/*.whl
|
|
115
|
+
"$py" -m pip check
|
|
116
|
+
"$py" - <<'PY'
|
|
117
|
+
import importlib.metadata
|
|
118
|
+
import platform
|
|
119
|
+
import sys
|
|
120
|
+
import impregcalc
|
|
121
|
+
|
|
122
|
+
assert platform.machine().lower() in {"aarch64", "arm64"}
|
|
123
|
+
assert impregcalc.__version__ == importlib.metadata.version("impregcalc")
|
|
124
|
+
assert "tkinter" not in sys.modules
|
|
125
|
+
assert "matplotlib" not in sys.modules
|
|
126
|
+
print(platform.machine(), impregcalc.__version__, impregcalc.__file__)
|
|
127
|
+
PY
|
|
128
|
+
"$RUNNER_TEMP/$IMPREGCALC_WHEEL_VENV/bin/impregcalc" --help
|
|
129
|
+
"$RUNNER_TEMP/$IMPREGCALC_WHEEL_VENV/bin/impregcalc" calculate \
|
|
130
|
+
examples/co_ru_iwi.json \
|
|
131
|
+
--output "$RUNNER_TEMP/$IMPREGCALC_CI_OUTPUT/wheel-recipe.md"
|
|
132
|
+
xvfb-run -a "$py" tests/gui_widget_smoke.py \
|
|
133
|
+
"$RUNNER_TEMP/$IMPREGCALC_CI_OUTPUT/wheel-gui.md"
|
|
134
|
+
- name: Clean isolated files and verify checkout
|
|
135
|
+
if: always()
|
|
136
|
+
run: |
|
|
137
|
+
python - <<'PY'
|
|
138
|
+
import os
|
|
139
|
+
from pathlib import Path
|
|
140
|
+
import shutil
|
|
141
|
+
|
|
142
|
+
runner_temp = Path(os.environ["RUNNER_TEMP"]).resolve()
|
|
143
|
+
workspace = Path(os.environ["GITHUB_WORKSPACE"]).resolve()
|
|
144
|
+
for variable in (
|
|
145
|
+
"IMPREGCALC_CI_VENV",
|
|
146
|
+
"IMPREGCALC_WHEEL_VENV",
|
|
147
|
+
"IMPREGCALC_CI_OUTPUT",
|
|
148
|
+
):
|
|
149
|
+
target = (runner_temp / os.environ[variable]).resolve()
|
|
150
|
+
if runner_temp not in target.parents:
|
|
151
|
+
raise RuntimeError(f"Refusing to clean outside runner temp: {target}")
|
|
152
|
+
shutil.rmtree(target, ignore_errors=True)
|
|
153
|
+
for relative in (
|
|
154
|
+
"build",
|
|
155
|
+
"dist",
|
|
156
|
+
".mypy_cache",
|
|
157
|
+
".pytest_cache",
|
|
158
|
+
".ruff_cache",
|
|
159
|
+
".coverage",
|
|
160
|
+
"htmlcov",
|
|
161
|
+
):
|
|
162
|
+
target = (workspace / relative).resolve()
|
|
163
|
+
if workspace not in target.parents:
|
|
164
|
+
raise RuntimeError(f"Refusing to clean outside workspace: {target}")
|
|
165
|
+
if target.is_dir():
|
|
166
|
+
shutil.rmtree(target)
|
|
167
|
+
elif target.exists():
|
|
168
|
+
target.unlink()
|
|
169
|
+
for target in workspace.rglob("__pycache__"):
|
|
170
|
+
if workspace in target.resolve().parents:
|
|
171
|
+
shutil.rmtree(target)
|
|
172
|
+
PY
|
|
173
|
+
test -z "$(git status --porcelain)"
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
name: macOS GUI compatibility
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: impregcalc-macos-${{ github.event.pull_request.number || github.ref }}
|
|
15
|
+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
macos:
|
|
19
|
+
name: ${{ matrix.label }} / Python ${{ matrix.python }}
|
|
20
|
+
strategy:
|
|
21
|
+
fail-fast: false
|
|
22
|
+
matrix:
|
|
23
|
+
include:
|
|
24
|
+
- label: macos-15
|
|
25
|
+
python: "3.10"
|
|
26
|
+
architecture: arm64
|
|
27
|
+
- label: macos-15-intel
|
|
28
|
+
python: "3.13"
|
|
29
|
+
architecture: x86_64
|
|
30
|
+
runs-on: ${{ matrix.label }}
|
|
31
|
+
timeout-minutes: 35
|
|
32
|
+
env:
|
|
33
|
+
MPLBACKEND: Agg
|
|
34
|
+
steps:
|
|
35
|
+
- name: Check out source
|
|
36
|
+
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
|
37
|
+
with:
|
|
38
|
+
persist-credentials: false
|
|
39
|
+
- name: Set up Python
|
|
40
|
+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
41
|
+
with:
|
|
42
|
+
python-version: ${{ matrix.python }}
|
|
43
|
+
- name: Confirm OS, architecture, Tk, and absence of Qt
|
|
44
|
+
env:
|
|
45
|
+
EXPECTED_ARCH: ${{ matrix.architecture }}
|
|
46
|
+
run: |
|
|
47
|
+
test "$(uname -m)" = "$EXPECTED_ARCH"
|
|
48
|
+
sw_vers
|
|
49
|
+
python -c 'import platform, tkinter; print(platform.python_version(), tkinter.TkVersion)'
|
|
50
|
+
python - <<'PY'
|
|
51
|
+
import importlib.util
|
|
52
|
+
for name in ("PyQt5", "PyQt6", "PySide2", "PySide6"):
|
|
53
|
+
assert importlib.util.find_spec(name) is None, name
|
|
54
|
+
PY
|
|
55
|
+
- name: Install source in a virtual environment
|
|
56
|
+
run: |
|
|
57
|
+
python -m venv "$RUNNER_TEMP/impregcalc-macos"
|
|
58
|
+
"$RUNNER_TEMP/impregcalc-macos/bin/python" -m pip install --upgrade pip
|
|
59
|
+
"$RUNNER_TEMP/impregcalc-macos/bin/python" -m pip install -e ".[dev,plot]"
|
|
60
|
+
"$RUNNER_TEMP/impregcalc-macos/bin/python" -m pip check
|
|
61
|
+
- name: Scientific, CLI, and GUI-import tests
|
|
62
|
+
run: |
|
|
63
|
+
py="$RUNNER_TEMP/impregcalc-macos/bin/python"
|
|
64
|
+
"$py" -m pytest tests/unit tests/integration tests/gui
|
|
65
|
+
"$py" -m impregcalc.cli validate examples/co_ru_iwi.json
|
|
66
|
+
- name: Real Tk window workflow and normal process exit
|
|
67
|
+
run: |
|
|
68
|
+
py="$RUNNER_TEMP/impregcalc-macos/bin/python"
|
|
69
|
+
"$py" tests/gui_widget_smoke.py "$RUNNER_TEMP/macos-gui-recipe.md"
|
|
70
|
+
test -s "$RUNNER_TEMP/macos-gui-recipe.md"
|
|
71
|
+
- name: Explicit Agg plot backend and export
|
|
72
|
+
run: |
|
|
73
|
+
py="$RUNNER_TEMP/impregcalc-macos/bin/python"
|
|
74
|
+
"$py" -m impregcalc.cli calculate examples/co_ru_iwi.json \
|
|
75
|
+
--output "$RUNNER_TEMP/macos-recipe.xlsx" \
|
|
76
|
+
--plot "$RUNNER_TEMP/macos-recipe.pdf"
|
|
77
|
+
"$py" -c 'import matplotlib; assert "agg" in matplotlib.get_backend().lower()'
|
|
78
|
+
test -s "$RUNNER_TEMP/macos-recipe.xlsx"
|
|
79
|
+
test -s "$RUNNER_TEMP/macos-recipe.pdf"
|
|
80
|
+
- name: Build and clean-wheel installation
|
|
81
|
+
run: |
|
|
82
|
+
py="$RUNNER_TEMP/impregcalc-macos/bin/python"
|
|
83
|
+
"$py" -m build
|
|
84
|
+
"$py" -m twine check dist/*
|
|
85
|
+
python -m venv "$RUNNER_TEMP/impregcalc-wheel"
|
|
86
|
+
wheel_py="$RUNNER_TEMP/impregcalc-wheel/bin/python"
|
|
87
|
+
"$wheel_py" -m pip install dist/*.whl
|
|
88
|
+
"$wheel_py" -m pip check
|
|
89
|
+
"$wheel_py" -c 'import impregcalc, sys; assert "tkinter" not in sys.modules'
|
|
90
|
+
"$RUNNER_TEMP/impregcalc-wheel/bin/impregcalc" calculate \
|
|
91
|
+
examples/co_ru_iwi.json --output "$RUNNER_TEMP/wheel-recipe.md"
|
|
92
|
+
"$wheel_py" tests/gui_widget_smoke.py "$RUNNER_TEMP/wheel-gui.md"
|
|
93
|
+
test -s "$RUNNER_TEMP/wheel-recipe.md"
|
|
94
|
+
test -s "$RUNNER_TEMP/wheel-gui.md"
|
|
95
|
+
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
build:
|
|
9
|
+
if: github.event.release.prerelease == false
|
|
10
|
+
runs-on: ubuntu-24.04
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
steps:
|
|
14
|
+
- name: Check out tagged source
|
|
15
|
+
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
|
16
|
+
with:
|
|
17
|
+
persist-credentials: false
|
|
18
|
+
- name: Set up Python
|
|
19
|
+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.12"
|
|
22
|
+
- name: Build and verify tagged version
|
|
23
|
+
env:
|
|
24
|
+
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
|
25
|
+
run: |
|
|
26
|
+
python -m pip install --upgrade pip build twine
|
|
27
|
+
python -m build
|
|
28
|
+
python -m twine check dist/*
|
|
29
|
+
python -m venv /tmp/impregcalc-release-wheel
|
|
30
|
+
/tmp/impregcalc-release-wheel/bin/python -m pip install dist/*.whl
|
|
31
|
+
/tmp/impregcalc-release-wheel/bin/python -m pip check
|
|
32
|
+
/tmp/impregcalc-release-wheel/bin/python - <<'PY'
|
|
33
|
+
import importlib.metadata
|
|
34
|
+
import os
|
|
35
|
+
import sys
|
|
36
|
+
import impregcalc
|
|
37
|
+
|
|
38
|
+
expected = os.environ["RELEASE_TAG"].removeprefix("v")
|
|
39
|
+
assert impregcalc.__version__ == expected
|
|
40
|
+
assert importlib.metadata.version("impregcalc") == expected
|
|
41
|
+
assert "tkinter" not in sys.modules
|
|
42
|
+
PY
|
|
43
|
+
/tmp/impregcalc-release-wheel/bin/impregcalc --help
|
|
44
|
+
/tmp/impregcalc-release-wheel/bin/impregcalc calculate \
|
|
45
|
+
examples/co_ru_iwi.json --output /tmp/impregcalc-release-example.md
|
|
46
|
+
- name: Upload distributions
|
|
47
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
48
|
+
with:
|
|
49
|
+
name: python-package-distributions
|
|
50
|
+
path: dist/
|
|
51
|
+
if-no-files-found: error
|
|
52
|
+
|
|
53
|
+
publish:
|
|
54
|
+
needs: build
|
|
55
|
+
runs-on: ubuntu-24.04
|
|
56
|
+
environment:
|
|
57
|
+
name: pypi
|
|
58
|
+
url: https://pypi.org/p/impregcalc
|
|
59
|
+
permissions:
|
|
60
|
+
id-token: write
|
|
61
|
+
steps:
|
|
62
|
+
- name: Download distributions
|
|
63
|
+
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
|
|
64
|
+
with:
|
|
65
|
+
name: python-package-distributions
|
|
66
|
+
path: dist/
|
|
67
|
+
- name: Publish with Trusted Publishing
|
|
68
|
+
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
|
|
69
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes will be recorded here. ImpregCalc follows semantic versioning
|
|
4
|
+
while scientific definition corrections may appear in patch releases.
|
|
5
|
+
|
|
6
|
+
## 0.1.0 — unreleased
|
|
7
|
+
|
|
8
|
+
- Initial elemental-metal, metal-oxide, and precursor loading engine.
|
|
9
|
+
- Final-catalyst and support-relative mass-balance conventions.
|
|
10
|
+
- Hydrate-dot formula parser and precursor assay correction.
|
|
11
|
+
- Co-impregnation, atomic-ratio promoter, IWI/wet liquid planning, and cycle splits.
|
|
12
|
+
- Python API, CLI, Tkinter GUI, JSON/Markdown/CSV/XLSX and figure export.
|
|
13
|
+
|
|
14
|
+
The conditions for 1.0.0 are not met. They require external-user experience,
|
|
15
|
+
definition-stable workflows, and suitable public experimental validation.
|
|
16
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use ImpregCalc, please cite this software and the scientific references documented in the repository."
|
|
3
|
+
title: "ImpregCalc"
|
|
4
|
+
type: software
|
|
5
|
+
version: 0.1.0
|
|
6
|
+
authors:
|
|
7
|
+
- family-names: Kim
|
|
8
|
+
given-names: Hyun Dong
|
|
9
|
+
repository-code: "https://github.com/hdkim99/ImpregCalc"
|
|
10
|
+
url: "https://github.com/hdkim99/ImpregCalc"
|
|
11
|
+
license: MIT
|
|
12
|
+
keywords:
|
|
13
|
+
- catalysis
|
|
14
|
+
- catalyst preparation
|
|
15
|
+
- impregnation
|
|
16
|
+
- stoichiometry
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thank you for improving ImpregCalc. Do not put unpublished, proprietary,
|
|
4
|
+
export-controlled, or otherwise confidential research data in a public issue or pull
|
|
5
|
+
request.
|
|
6
|
+
|
|
7
|
+
## Scientific changes
|
|
8
|
+
|
|
9
|
+
Every scientific-core change must state:
|
|
10
|
+
|
|
11
|
+
1. the equation or definition and the convention it implements;
|
|
12
|
+
2. every input/output unit and loading denominator;
|
|
13
|
+
3. assumptions, validity range, and unsupported cases;
|
|
14
|
+
4. an original publication, established textbook, or peer-reviewed review when the
|
|
15
|
+
change is not a direct dimensional/stoichiometric derivation;
|
|
16
|
+
5. an independent numerical validation (hand calculation, literature benchmark, or
|
|
17
|
+
controlled synthetic benchmark);
|
|
18
|
+
6. boundary and invalid-input behavior plus a regression test.
|
|
19
|
+
|
|
20
|
+
Do not add an undocumented coefficient, threshold, uncertainty, or confidence claim.
|
|
21
|
+
Do not infer model validity from R² alone.
|
|
22
|
+
|
|
23
|
+
## GUI and plotting changes
|
|
24
|
+
|
|
25
|
+
Record the supported platform, dependency change, backend impact, macOS smoke result,
|
|
26
|
+
and proof that CLI/core imports remain GUI-independent. Do not add Qt without a
|
|
27
|
+
documented need, one binding only, clean-environment macOS lifecycle validation, and
|
|
28
|
+
explicit backend checks.
|
|
29
|
+
|
|
30
|
+
## Local checks
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
python -m pip install -e ".[dev,plot]"
|
|
34
|
+
ruff format --check .
|
|
35
|
+
ruff check .
|
|
36
|
+
mypy src
|
|
37
|
+
pytest
|
|
38
|
+
python -m build
|
|
39
|
+
twine check dist/*
|
|
40
|
+
```
|
|
41
|
+
|
impregcalc-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hyun Dong Kim
|
|
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 deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
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 all
|
|
13
|
+
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 FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|