pypsbuilder 2.6.5__tar.gz → 2.6.7__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.
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/.gitignore +3 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/.pre-commit-config.yaml +1 -1
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/CHANGELOG.md +10 -1
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/CONTRIBUTING.md +1 -1
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/PKG-INFO +7 -7
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/README.md +4 -4
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/psbuilders-tutorial.rst +14 -9
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pyproject.toml +2 -2
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/__init__.py +1 -1
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/tcinit.py +38 -6
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/tests/test_tcinit.py +83 -6
- pypsbuilder-2.6.5/uv.lock +0 -4132
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/.github/dependabot.yml +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/.github/workflows/release.yml +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/.github/workflows/testing.yml +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/.github/workflows/testrelease.yml +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/.readthedocs.yaml +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/.zenodo.json +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/AUTHORS.md +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/LICENSE +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/codecov.yml +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/_static/theme_overrides.css +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/api/pypsbuilder.psclasses.Dogmin.rst +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/api/pypsbuilder.psclasses.InvPoint.rst +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/api/pypsbuilder.psclasses.PTsection.rst +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/api/pypsbuilder.psclasses.PXsection.rst +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/api/pypsbuilder.psclasses.TCResult.rst +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/api/pypsbuilder.psclasses.TCResultSet.rst +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/api/pypsbuilder.psclasses.TXsection.rst +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/api/pypsbuilder.psclasses.UniLine.rst +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/api/pypsbuilder.psexplorer.PTPS.rst +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/api/pypsbuilder.psexplorer.PXPS.rst +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/api/pypsbuilder.psexplorer.TXPS.rst +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/api/pypsbuilder.tcapi.TC34API.rst +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/api/pypsbuilder.tcapi.TC35API.rst +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/api.rst +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/authors.rst +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/command-line.rst +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/conf.py +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/create_environment.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/crossing.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/delta.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/install_locally.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/invsearch.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/isopleths_1.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/isopleths_2.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/modes.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/psbuilder_areas.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/psbuilder_dogmin.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/psbuilder_finished.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/psbuilder_highlight.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/psbuilder_init.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/psbuilder_inv.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/psbuilder_modes.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/psbuilder_uni.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/psiso_alm.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/psiso_labelkey.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/psiso_mode.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/psiso_other.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/psshow_out.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/ptpath.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/show_data.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/show_grid.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/show_label.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/show_out.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/show_plain.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/images/status.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/index.rst +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/psexplorer-tutorial.rst +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/docs/readme.rst +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/environment.yml +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/examples/avgpelite/tc-avgpelite.txt +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/examples/avgpelite/tc-ds62.txt +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/examples/avgpelite/tc-mp50MnNCKFMASHTO.txt +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/examples/avgpelite/tc-prefs.txt +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/examples/avgpelite_34/tc-6axmn.txt +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/examples/avgpelite_34/tc-avgpelite.txt +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/examples/avgpelite_34/tc-ds62.txt +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/examples/avgpelite_34/tc-prefs.txt +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/examples/outputs/inv1-ic.txt +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/examples/outputs/inv1-log.txt +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/examples/outputs/inv2-ic.txt +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/examples/outputs/inv2-log.txt +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/examples/outputs/inv3-ic.txt +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/examples/outputs/inv3-log.txt +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/examples/outputs/uni1-ic.txt +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/examples/outputs/uni1-log.txt +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/examples/outputs/uni2-ic.txt +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/examples/outputs/uni2-log.txt +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/examples/outputs/uni3-ic.txt +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/examples/outputs/uni3-log.txt +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/notebooks/pypsbuilder.ipynb +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/images/ptbuilder.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/images/pxbuilder.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/images/pypsbuilder.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/images/txbuilder.png +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/psbuilders.py +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/psclasses.py +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/psexplorer.py +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/tcapi.py +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/tests/__init__.py +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/tests/test_pclasses.py +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/tests/test_psbuilders.py +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/tests/test_psclasses.py +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/tests/test_psexplorer.py +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/tests/test_tcapi.py +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/ui/addinv.ui +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/ui/adduni.ui +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/ui/compile_ui.sh +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/ui/ptbuilder.ui +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/ui/pxbuilder.ui +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/ui/txbuilder.ui +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/ui/uniguess.ui +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/ui_addinv.py +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/ui_adduni.py +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/ui_ptbuilder.py +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/ui_pxbuilder.py +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/ui_txbuilder.py +0 -0
- {pypsbuilder-2.6.5 → pypsbuilder-2.6.7}/pypsbuilder/ui_uniguess.py +0 -0
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
All notable pypsbuilder changes.
|
|
3
3
|
|
|
4
|
-
## [2.6.
|
|
4
|
+
## [2.6.7] - 2026-08-29
|
|
5
|
+
### Added
|
|
6
|
+
- `tcinit` now prompts for the P-T range (`[pmin, pmax, tmin, tmax]`), used to set the generated scriptfile's `diagramPT`/`calcP`/`calcT` lines
|
|
7
|
+
- `tcinit` creates the destination directory automatically when it doesn't exist yet but its parent does
|
|
8
|
+
|
|
9
|
+
## [2.6.6] - 2026-08-29
|
|
10
|
+
### Fixed
|
|
11
|
+
- project extra jupyter renamed to lab
|
|
12
|
+
|
|
13
|
+
## [2.6.5] - 2026-08-29
|
|
5
14
|
### Added
|
|
6
15
|
- `Import from JSON` menu item in ptbuilder/txbuilder/pxbuilder to batch-import invariant points and univariant lines JSON
|
|
7
16
|
- THERMOCALC 3.51 support in `tcinit`
|
|
@@ -52,7 +52,7 @@ Ready to contribute? Here's how to set up `pypsbuilder` for local development.
|
|
|
52
52
|
|
|
53
53
|
2. Set up a development environment with [uv](https://docs.astral.sh/uv/) and create a branch for local development. See the "Contributing / development install" section in [README.md](README.md) for the full command reference (running tests, formatting/linting with ruff, pre-commit hooks).
|
|
54
54
|
```
|
|
55
|
-
$ uv sync --
|
|
55
|
+
$ uv sync --group dev
|
|
56
56
|
$ git checkout -b name-of-your-bugfix-or-feature
|
|
57
57
|
```
|
|
58
58
|
Now you can make your changes locally.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: pypsbuilder
|
|
3
|
-
Version: 2.6.
|
|
3
|
+
Version: 2.6.7
|
|
4
4
|
Summary: THERMOCALC front-end for constructing and analyzing PT pseudosections
|
|
5
5
|
Project-URL: Homepage, https://github.com/ondrolexa/pypsbuilder
|
|
6
6
|
Project-URL: Documentation, https://pypsbuilder.readthedocs.io
|
|
@@ -52,8 +52,8 @@ Provides-Extra: docs
|
|
|
52
52
|
Requires-Dist: sphinx; extra == 'docs'
|
|
53
53
|
Requires-Dist: sphinx-mdinclude; extra == 'docs'
|
|
54
54
|
Requires-Dist: sphinx-rtd-theme; extra == 'docs'
|
|
55
|
-
Provides-Extra:
|
|
56
|
-
Requires-Dist: jupyterlab; extra == '
|
|
55
|
+
Provides-Extra: lab
|
|
56
|
+
Requires-Dist: jupyterlab; extra == 'lab'
|
|
57
57
|
Provides-Extra: pyqt5
|
|
58
58
|
Requires-Dist: pyqt5; extra == 'pyqt5'
|
|
59
59
|
Provides-Extra: pyqt6
|
|
@@ -83,9 +83,9 @@ Create an isolated environment and install **pypsbuilder** into it. **You should
|
|
|
83
83
|
uv venv
|
|
84
84
|
uv pip install pypsbuilder[pyqt6]
|
|
85
85
|
|
|
86
|
-
JupyterLab could also be installed providing the `
|
|
86
|
+
JupyterLab could also be installed providing the `lab` option:
|
|
87
87
|
|
|
88
|
-
uv pip install pypsbuilder[pyqt6,
|
|
88
|
+
uv pip install pypsbuilder[pyqt6,lab]
|
|
89
89
|
|
|
90
90
|
### Using pip and venv
|
|
91
91
|
|
|
@@ -116,9 +116,9 @@ and install **pypsbuilder** using pip within the environment. **You should choos
|
|
|
116
116
|
|
|
117
117
|
pip install pypsbuilder[pyqt6]
|
|
118
118
|
|
|
119
|
-
JupyterLab could also be installed providing the `
|
|
119
|
+
JupyterLab could also be installed providing the `lab` option:
|
|
120
120
|
|
|
121
|
-
pip install pypsbuilder[pyqt6,
|
|
121
|
+
pip install pypsbuilder[pyqt6,lab]
|
|
122
122
|
|
|
123
123
|
## I'm using conda or mamba to manage environments
|
|
124
124
|
|
|
@@ -18,9 +18,9 @@ Create an isolated environment and install **pypsbuilder** into it. **You should
|
|
|
18
18
|
uv venv
|
|
19
19
|
uv pip install pypsbuilder[pyqt6]
|
|
20
20
|
|
|
21
|
-
JupyterLab could also be installed providing the `
|
|
21
|
+
JupyterLab could also be installed providing the `lab` option:
|
|
22
22
|
|
|
23
|
-
uv pip install pypsbuilder[pyqt6,
|
|
23
|
+
uv pip install pypsbuilder[pyqt6,lab]
|
|
24
24
|
|
|
25
25
|
### Using pip and venv
|
|
26
26
|
|
|
@@ -51,9 +51,9 @@ and install **pypsbuilder** using pip within the environment. **You should choos
|
|
|
51
51
|
|
|
52
52
|
pip install pypsbuilder[pyqt6]
|
|
53
53
|
|
|
54
|
-
JupyterLab could also be installed providing the `
|
|
54
|
+
JupyterLab could also be installed providing the `lab` option:
|
|
55
55
|
|
|
56
|
-
pip install pypsbuilder[pyqt6,
|
|
56
|
+
pip install pypsbuilder[pyqt6,lab]
|
|
57
57
|
|
|
58
58
|
## I'm using conda or mamba to manage environments
|
|
59
59
|
|
|
@@ -65,18 +65,23 @@ Using tcinit to setup working directory
|
|
|
65
65
|
---------------------------------------
|
|
66
66
|
|
|
67
67
|
For TC3.5 you can use the ``tcinit`` command to initialize a working
|
|
68
|
-
directory. Run it
|
|
68
|
+
directory. Run it and answer the prompts::
|
|
69
69
|
|
|
70
70
|
$ tcinit
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
72
|
+
You will be asked for a project directory (defaults to the current
|
|
73
|
+
directory; if it doesn't exist yet but its parent does, it is created for
|
|
74
|
+
you automatically), a project name (max 8 characters), the P-T range to use
|
|
75
|
+
(``[pmin, pmax, tmin, tmax]``, defaulting to ``[1.9, 10.1, 345, 805]`` and
|
|
76
|
+
written into the scriptfile's ``diagramPT``/``calcP``/``calcT`` lines), and
|
|
77
|
+
one of four bundled datasets/a-x files: ``metapelite``, ``metabasite``,
|
|
78
|
+
``igg25`` (igneous, White et al. 2025 update) or ``igw24`` (igneous, Weller
|
|
79
|
+
et al. 2024). It then downloads THERMOCALC 3.51 for your platform (Linux,
|
|
80
|
+
Windows or macOS). The chosen dataset, a-x file, starting guesses and
|
|
81
|
+
preferences file are written into the project directory, already tagged
|
|
82
|
+
with the ``%{PSBGUESS-...}``, ``%{PSBCALC-...}`` and ``%{PSBBULK-...}``
|
|
83
|
+
blocks described above, so the resulting scriptfile works with
|
|
84
|
+
``ptbuilder``/``txbuilder``/``pxbuilder`` out of the box.
|
|
80
85
|
|
|
81
86
|
|
|
82
87
|
New P-T pseudosection project
|
|
@@ -34,12 +34,12 @@ dependencies = [
|
|
|
34
34
|
[project.optional-dependencies]
|
|
35
35
|
pyqt5 = ["pyqt5"]
|
|
36
36
|
pyqt6 = ["pyqt6"]
|
|
37
|
-
|
|
37
|
+
lab = ["jupyterlab"]
|
|
38
38
|
tests = ["pytest", "pytest-cov"]
|
|
39
39
|
docs = ["sphinx", "sphinx_mdinclude", "sphinx_rtd_theme"]
|
|
40
40
|
|
|
41
41
|
[dependency-groups]
|
|
42
|
-
dev = ["pypsbuilder[pyqt6,
|
|
42
|
+
dev = ["pypsbuilder[pyqt6,lab,tests,docs]", "ruff>=0.6", "pre-commit"]
|
|
43
43
|
|
|
44
44
|
[project.urls]
|
|
45
45
|
Homepage = "https://github.com/ondrolexa/pypsbuilder"
|
|
@@ -47,6 +47,9 @@ def tcprojinit():
|
|
|
47
47
|
dir_needed = False
|
|
48
48
|
else:
|
|
49
49
|
print(f"ERROR: {dest} is not empty...")
|
|
50
|
+
elif not dest.exists() and dest.parent.is_dir():
|
|
51
|
+
dest.mkdir()
|
|
52
|
+
dir_needed = False
|
|
50
53
|
else:
|
|
51
54
|
print(f"ERROR: {dest} is not valid directory...")
|
|
52
55
|
|
|
@@ -71,6 +74,28 @@ def tcprojinit():
|
|
|
71
74
|
else:
|
|
72
75
|
projname_needed = False
|
|
73
76
|
|
|
77
|
+
range_needed = True
|
|
78
|
+
while range_needed:
|
|
79
|
+
range_raw = input("Enter [pmin, pmax, tmin, tmax] [1.9, 10.1, 345, 805]: ")
|
|
80
|
+
if range_raw == "":
|
|
81
|
+
pmin, pmax, tmin, tmax = 1.9, 10.1, 345, 805
|
|
82
|
+
else:
|
|
83
|
+
try:
|
|
84
|
+
pmin, pmax, tmin, tmax = (
|
|
85
|
+
float(v) for v in range_raw.strip("[]").split(",")
|
|
86
|
+
)
|
|
87
|
+
except ValueError:
|
|
88
|
+
print("ERROR: enter four comma-separated numbers")
|
|
89
|
+
continue
|
|
90
|
+
if pmax <= pmin:
|
|
91
|
+
print("ERROR: pmax must be greater than pmin")
|
|
92
|
+
elif tmax <= tmin:
|
|
93
|
+
print("ERROR: tmax must be greater than tmin")
|
|
94
|
+
else:
|
|
95
|
+
range_needed = False
|
|
96
|
+
|
|
97
|
+
pstep = (pmax - pmin) / 2
|
|
98
|
+
|
|
74
99
|
set_needed = True
|
|
75
100
|
sets = {1: "metapelite", 2: "metabasite", 3: "igg25", 4: "igw24"}
|
|
76
101
|
while set_needed:
|
|
@@ -186,7 +211,15 @@ def tcprojinit():
|
|
|
186
211
|
# create project file
|
|
187
212
|
with open(dest / f"tc-{projname}.txt", "w") as f:
|
|
188
213
|
content = string.Template(tcprj_tmpl).substitute(
|
|
189
|
-
system=system,
|
|
214
|
+
system=system,
|
|
215
|
+
project=projname,
|
|
216
|
+
samecoding=samecoding,
|
|
217
|
+
guesses=guesses,
|
|
218
|
+
pmin=pmin,
|
|
219
|
+
pmax=pmax,
|
|
220
|
+
tmin=tmin,
|
|
221
|
+
tmax=tmax,
|
|
222
|
+
step=pstep,
|
|
190
223
|
)[1:]
|
|
191
224
|
f.write(content)
|
|
192
225
|
|
|
@@ -803,18 +836,17 @@ tozero no
|
|
|
803
836
|
% which conditions
|
|
804
837
|
% ================
|
|
805
838
|
|
|
806
|
-
diagramPT
|
|
839
|
+
diagramPT $pmin $pmax $tmin $tmax
|
|
807
840
|
|
|
808
841
|
% ================
|
|
809
842
|
% psbuilder blocks
|
|
810
843
|
% ================
|
|
811
844
|
|
|
812
845
|
%{PSBCALC-BEGIN}
|
|
813
|
-
calcP
|
|
814
|
-
calcT
|
|
846
|
+
calcP $pmin $pmax $step
|
|
847
|
+
calcT $tmin $tmax
|
|
815
848
|
calctatp yes
|
|
816
|
-
with
|
|
817
|
-
zeromodeisopleth q
|
|
849
|
+
with *
|
|
818
850
|
%{PSBCALC-END}
|
|
819
851
|
|
|
820
852
|
% =====================
|
|
@@ -115,7 +115,7 @@ def test_tcprojinit_all_platform_dataset_combinations(
|
|
|
115
115
|
):
|
|
116
116
|
dest = tmp_path / f"proj_{comp}_{choice}"
|
|
117
117
|
dest.mkdir()
|
|
118
|
-
inputs = iter([str(dest), "testproj", choice])
|
|
118
|
+
inputs = iter([str(dest), "testproj", "", choice])
|
|
119
119
|
|
|
120
120
|
with (
|
|
121
121
|
mock.patch("builtins.input", lambda *a: next(inputs)),
|
|
@@ -139,6 +139,11 @@ def test_tcprojinit_all_platform_dataset_combinations(
|
|
|
139
139
|
assert (dest / f"tc-ds{ds}.txt").read_text() == "fake dataset file content\n"
|
|
140
140
|
assert (dest / f"tc-{system}.txt").read_text() == "fake axfile content\n"
|
|
141
141
|
|
|
142
|
+
projfile = (dest / "tc-testproj.txt").read_text()
|
|
143
|
+
assert "diagramPT 1.9 10.1 345 805" in projfile
|
|
144
|
+
assert "calcP 1.9 10.1 4.1" in projfile
|
|
145
|
+
assert "calcT 345 805" in projfile
|
|
146
|
+
|
|
142
147
|
|
|
143
148
|
def test_tcprojinit_samecoding_extracted_from_prefix_matched_file(
|
|
144
149
|
tmp_path, synthetic_urls
|
|
@@ -148,7 +153,7 @@ def test_tcprojinit_samecoding_extracted_from_prefix_matched_file(
|
|
|
148
153
|
this session."""
|
|
149
154
|
dest = tmp_path / "proj"
|
|
150
155
|
dest.mkdir()
|
|
151
|
-
inputs = iter([str(dest), "testproj", "4"]) # igw24
|
|
156
|
+
inputs = iter([str(dest), "testproj", "", "4"]) # igw24
|
|
152
157
|
|
|
153
158
|
with (
|
|
154
159
|
mock.patch("builtins.input", lambda *a: next(inputs)),
|
|
@@ -169,7 +174,7 @@ def test_tcprojinit_no_samecoding_file_falls_back_to_empty(tmp_path):
|
|
|
169
174
|
current code falls back to an empty string rather than raising."""
|
|
170
175
|
dest = tmp_path / "proj"
|
|
171
176
|
dest.mkdir()
|
|
172
|
-
inputs = iter([str(dest), "testproj", "1"]) # metapelite
|
|
177
|
+
inputs = iter([str(dest), "testproj", "", "1"]) # metapelite
|
|
173
178
|
|
|
174
179
|
cache = {
|
|
175
180
|
tcinit.exe_urls["linux"]: _exe_zip("tc351-linux-bundle", "tc351lin"),
|
|
@@ -192,6 +197,45 @@ def test_tcprojinit_no_samecoding_file_falls_back_to_empty(tmp_path):
|
|
|
192
197
|
assert projfile.exists()
|
|
193
198
|
|
|
194
199
|
|
|
200
|
+
def test_tcprojinit_creates_missing_directory_with_existing_parent(
|
|
201
|
+
tmp_path, synthetic_urls
|
|
202
|
+
):
|
|
203
|
+
dest = tmp_path / "newdir"
|
|
204
|
+
assert not dest.exists()
|
|
205
|
+
inputs = iter([str(dest), "testproj", "", "1"])
|
|
206
|
+
|
|
207
|
+
with (
|
|
208
|
+
mock.patch("builtins.input", lambda *a: next(inputs)),
|
|
209
|
+
mock.patch("pypsbuilder.tcinit.platform.system", return_value="Linux"),
|
|
210
|
+
mock.patch("pypsbuilder.tcinit.urlopen", _fake_urlopen(synthetic_urls)),
|
|
211
|
+
):
|
|
212
|
+
tcinit.tcprojinit()
|
|
213
|
+
|
|
214
|
+
assert dest.is_dir()
|
|
215
|
+
assert (dest / "tc-prefs.txt").exists()
|
|
216
|
+
assert (dest / "tc-testproj.txt").exists()
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def test_tcprojinit_rejects_missing_parent_directory(tmp_path, synthetic_urls, capsys):
|
|
220
|
+
dest = tmp_path / "missing" / "newdir"
|
|
221
|
+
assert not dest.parent.exists()
|
|
222
|
+
|
|
223
|
+
good_dest = tmp_path / "empty_proj"
|
|
224
|
+
good_dest.mkdir()
|
|
225
|
+
|
|
226
|
+
inputs = iter([str(dest), str(good_dest), "testproj", "", "1"])
|
|
227
|
+
|
|
228
|
+
with (
|
|
229
|
+
mock.patch("builtins.input", lambda *a: next(inputs)),
|
|
230
|
+
mock.patch("pypsbuilder.tcinit.platform.system", return_value="Linux"),
|
|
231
|
+
mock.patch("pypsbuilder.tcinit.urlopen", _fake_urlopen(synthetic_urls)),
|
|
232
|
+
):
|
|
233
|
+
tcinit.tcprojinit()
|
|
234
|
+
|
|
235
|
+
assert "is not valid directory" in capsys.readouterr().out
|
|
236
|
+
assert (good_dest / "tc-prefs.txt").exists()
|
|
237
|
+
|
|
238
|
+
|
|
195
239
|
def test_tcprojinit_rejects_nonempty_directory(tmp_path, synthetic_urls, capsys):
|
|
196
240
|
dest = tmp_path / "proj"
|
|
197
241
|
dest.mkdir()
|
|
@@ -200,7 +244,7 @@ def test_tcprojinit_rejects_nonempty_directory(tmp_path, synthetic_urls, capsys)
|
|
|
200
244
|
good_dest = tmp_path / "empty_proj"
|
|
201
245
|
good_dest.mkdir()
|
|
202
246
|
|
|
203
|
-
inputs = iter([str(dest), str(good_dest), "testproj", "1"])
|
|
247
|
+
inputs = iter([str(dest), str(good_dest), "testproj", "", "1"])
|
|
204
248
|
|
|
205
249
|
with (
|
|
206
250
|
mock.patch("builtins.input", lambda *a: next(inputs)),
|
|
@@ -216,7 +260,7 @@ def test_tcprojinit_rejects_nonempty_directory(tmp_path, synthetic_urls, capsys)
|
|
|
216
260
|
def test_tcprojinit_default_project_name(tmp_path, synthetic_urls):
|
|
217
261
|
dest = tmp_path / "proj"
|
|
218
262
|
dest.mkdir()
|
|
219
|
-
inputs = iter([str(dest), "", "1"]) # empty name -> default "project"
|
|
263
|
+
inputs = iter([str(dest), "", "", "1"]) # empty name -> default "project"
|
|
220
264
|
|
|
221
265
|
with (
|
|
222
266
|
mock.patch("builtins.input", lambda *a: next(inputs)),
|
|
@@ -229,13 +273,46 @@ def test_tcprojinit_default_project_name(tmp_path, synthetic_urls):
|
|
|
229
273
|
assert "scriptfile project" in (dest / "tc-prefs.txt").read_text()
|
|
230
274
|
|
|
231
275
|
|
|
276
|
+
def test_tcprojinit_range_validation_and_retry(tmp_path, synthetic_urls, capsys):
|
|
277
|
+
dest = tmp_path / "proj"
|
|
278
|
+
dest.mkdir()
|
|
279
|
+
inputs = iter(
|
|
280
|
+
[
|
|
281
|
+
str(dest),
|
|
282
|
+
"testproj",
|
|
283
|
+
"not, a, number, here", # unparseable -> retry
|
|
284
|
+
"10, 2, 345, 805", # pmax <= pmin -> retry
|
|
285
|
+
"1.9, 10.1, 805, 345", # tmax <= tmin -> retry
|
|
286
|
+
"2, 12, 400, 700", # valid
|
|
287
|
+
"1",
|
|
288
|
+
]
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
with (
|
|
292
|
+
mock.patch("builtins.input", lambda *a: next(inputs)),
|
|
293
|
+
mock.patch("pypsbuilder.tcinit.platform.system", return_value="Linux"),
|
|
294
|
+
mock.patch("pypsbuilder.tcinit.urlopen", _fake_urlopen(synthetic_urls)),
|
|
295
|
+
):
|
|
296
|
+
tcinit.tcprojinit()
|
|
297
|
+
|
|
298
|
+
out = capsys.readouterr().out
|
|
299
|
+
assert "ERROR: enter four comma-separated numbers" in out
|
|
300
|
+
assert "ERROR: pmax must be greater than pmin" in out
|
|
301
|
+
assert "ERROR: tmax must be greater than tmin" in out
|
|
302
|
+
|
|
303
|
+
projfile = (dest / "tc-testproj.txt").read_text()
|
|
304
|
+
assert "diagramPT 2.0 12.0 400.0 700.0" in projfile
|
|
305
|
+
assert "calcP 2.0 12.0 5.0" in projfile
|
|
306
|
+
assert "calcT 400.0 700.0" in projfile
|
|
307
|
+
|
|
308
|
+
|
|
232
309
|
def test_tcprojinit_project_name_sanitization(tmp_path, synthetic_urls):
|
|
233
310
|
dest = tmp_path / "proj"
|
|
234
311
|
dest.mkdir()
|
|
235
312
|
# spaces replaced, non-ascii stripped, then re-entered because
|
|
236
313
|
# "a b" -> "a_b" is valid on first pass (no retry needed here);
|
|
237
314
|
# test a name that's too long first to exercise the retry loop
|
|
238
|
-
inputs = iter([str(dest), "toolongname123", "short nm", "1"])
|
|
315
|
+
inputs = iter([str(dest), "toolongname123", "short nm", "", "1"])
|
|
239
316
|
|
|
240
317
|
with (
|
|
241
318
|
mock.patch("builtins.input", lambda *a: next(inputs)),
|