Skip to content
5 changes: 3 additions & 2 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ jobs:
python-version:
- "3.12"
- "3.13"
- "3.14"
extra-doctest-ignore:
- ""
# The OrderedDict __str__ method changed in Python 3.12 so doctests in the ytools.py module will fail
Expand All @@ -47,9 +48,9 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Install Python dependencies
Expand Down
18 changes: 9 additions & 9 deletions .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ jobs:
- windows-2022
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: "3.13"
- name: Build wheels
uses: pypa/cibuildwheel@v2.23.3
uses: pypa/cibuildwheel@v3.4.0
- name: Upload artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
path: wheelhouse/*.whl
Expand All @@ -51,9 +51,9 @@ jobs:
needs: [build_wheels]
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: "3.13"
- name: Install dependencies and build sdist
Expand All @@ -64,13 +64,13 @@ jobs:
$PYTHON_VENV/bin/pip install -v build
$PYTHON_VENV/bin/python -m build -s .
- name: Download wheels
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
pattern: cibw-wheels-*
merge-multiple: true
path: dist/
- name: Upload wheels and sdist
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: wheels-and-sdist
path: dist/
Expand All @@ -79,4 +79,4 @@ jobs:
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
run: |
python -m pip install --upgrade packaging twine
python -m twine upload --verbose dist/*
# python -m twine upload --verbose dist/*
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ line-length = 88
build-frontend = "build"
archs = ["auto64"]
skip = [
"pp*", # PyPy
"*musl*", # musllinux
"cp3??t-*", # Free-threading on all platforms
"*musl*", # musllinux
]


Expand Down
24 changes: 20 additions & 4 deletions pyyeti/guitools.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,16 @@
import os
import sys
from functools import wraps
import tkinter as tk
from tkinter import filedialog
import tkinter.font as tkFont
from tkinter import ttk

try:
import tkinter as tk
from tkinter import filedialog
import tkinter.font as tkFont
from tkinter import ttk
except ImportError:
HAVE_TKINTER = False
else:
HAVE_TKINTER = True


LASTOPENDIR = None
Expand Down Expand Up @@ -106,6 +112,9 @@ def askopenfilename(title=None, filetypes=None, initialdir=None): # pragma: no
filename = guitools.askopenfilename(filetypes=filetypes)

"""
if not HAVE_TKINTER:
msg = "tkinter not available, cannot create GUI dialog"
raise ImportError(msg)
global LASTOPENDIR
root = tk.Tk()
root.withdraw()
Expand Down Expand Up @@ -158,6 +167,9 @@ def asksaveasfilename(title=None, filetypes=None, initialdir=None): # pragma: n
filename = guitools.asksaveasfilename(filetypes=filetypes)

"""
if not HAVE_TKINTER:
msg = "tkinter not available, cannot create GUI dialog"
raise ImportError(msg)
global LASTSAVEDIR
root = tk.Tk()
root.withdraw()
Expand Down Expand Up @@ -357,6 +369,10 @@ def __init__(
topstring : string; optional
String to print above table
"""
if not HAVE_TKINTER:
msg = "tkinter not available, cannot create GUI dialog"
raise ImportError(msg)

self.root = tk.Tk()
self.root.title(title)
self.tree = None
Expand Down
2 changes: 1 addition & 1 deletion pyyeti/nastran/n2p.py
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ def replace_basic_cs(uset, new_cs_id, new_cs_in_basic=None):

# extract the GRID part of the uset table to a numpy array:
grids = uset_new.index.get_level_values("dof") > 0
xyz = uset_new.loc[grids, "x":"z"].values # .copy()
xyz = uset_new.loc[grids, "x":"z"].values.copy()
nrows = xyz.shape[0]

current_cs_ids = xyz[1::6, 0].astype(int)
Expand Down
7 changes: 5 additions & 2 deletions pyyeti/tests/test_cb.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from io import StringIO
import tempfile
import os
import re
import inspect
from pyyeti import cb, ytools, nastran
from pyyeti.nastran import op2, n2p, op4
Expand Down Expand Up @@ -694,7 +695,8 @@ def test_cbcoordchk():
assert abs(chk0.maxerr).max() < 1e-5

# a case where the refpoint_chk should be 'fail':
with pytest.warns(la.LinAlgWarning, match=r"Ill\-conditioned matrix"):
regex = re.compile(r"ill\-conditioned matrix", re.IGNORECASE)
with pytest.warns(la.LinAlgWarning, match=regex):
chk2 = cb.cbcoordchk(kaa, b, [25, 26, 27, 31, 32, 33], verbose=False)
assert chk2.refpoint_chk == "fail"

Expand Down Expand Up @@ -1045,7 +1047,8 @@ def test_cbcoordchk3():
assert abs(chk0.maxerr).max() < 1e-5

# a case where the refpoint_chk should be 'fail':
with pytest.warns(la.LinAlgWarning, match=r"Ill\-conditioned matrix"):
regex = re.compile(r"ill\-conditioned matrix", re.IGNORECASE)
with pytest.warns(la.LinAlgWarning, match=regex):
chk2 = cb.cbcoordchk(kaa, b, [25, 26, 27, 31, 32, 33], verbose=False)
assert chk2.refpoint_chk == "fail"

Expand Down
7 changes: 4 additions & 3 deletions pyyeti/tests/test_fdepsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def compare(fde1, fde2):


def test_fdepsd_absacce():
np.random.seed(1)
rng = np.random.default_rng(1)
TF = 60 # make a 60 second signal
sp = 1.0
spec = np.array([[20, sp], [50, sp]])
Expand All @@ -35,6 +35,7 @@ def test_fdepsd_absacce():
df=1 / TF,
winends=dict(portion=10),
gettime=True,
rng=rng,
)
freq = np.arange(30.0, 50.1)
q = 25
Expand Down Expand Up @@ -169,9 +170,9 @@ def test_fdepsd_error():


def test_ski_slope():
# np.random.seed(1)
rng = np.random.default_rng(1)
spec = np.array([[20.0, 1.0], [100.0, 1.0], [150.0, 10.0], [1000.0, 10.0]])
sig, sr = psd.psd2time(spec, 20, 1000)
sig, sr = psd.psd2time(spec, 20, 1000, rng=rng)

sig[0] = sig.max()

Expand Down
31 changes: 31 additions & 0 deletions pyyeti/tests/test_guitools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import pytest
from pyyeti import guitools


@pytest.mark.parametrize("read", [True, False])
def test_get_file_name_no_tkinter(read, monkeypatch):
monkeypatch.setattr(guitools, "HAVE_TKINTER", False)
with pytest.raises(ImportError, match="tkinter not available.*cannot create GUI"):
guitools.get_file_name(None, read)


def test_askopenfilename_no_tkinter(monkeypatch):
monkeypatch.setattr(guitools, "HAVE_TKINTER", False)
with pytest.raises(ImportError, match="tkinter not available.*cannot create GUI"):
guitools.askopenfilename()


def test_asksaveasfilename_no_tkinter(monkeypatch):
monkeypatch.setattr(guitools, "HAVE_TKINTER", False)
with pytest.raises(ImportError, match="tkinter not available.*cannot create GUI"):
guitools.asksaveasfilename()


def test_multicolumnlistbox_no_tkinter(monkeypatch):
monkeypatch.setattr(guitools, "HAVE_TKINTER", False)
headers = ["First", "Middle", "Last"]
lst1 = ["Tony", "Jennifer", "Albert", "Marion"]
lst2 = ["J.", "M.", "E.", "K."]
lst3 = ["Anderson", "Smith", "Kingsley", "Cotter"]
with pytest.raises(ImportError, match="tkinter not available.*cannot create GUI"):
guitools.MultiColumnListbox("Select person", headers, [lst1, lst2, lst3])
5 changes: 4 additions & 1 deletion pyyeti/tests/test_n2p.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from scipy.io import matlab
import io
import os
import re
from pyyeti import nastran, cb
from pyyeti.nastran import n2p, op2, op4
import pytest
Expand Down Expand Up @@ -1948,7 +1949,9 @@ def test_badrbe3_warn():
uset = n2p.addgrid(None, np.arange(1, n + 1), "b", 0, np.column_stack((x, y, z)), 0)
uset = n2p.addgrid(uset, 100, "b", 0, [5, 5, 5], 0)
with pytest.warns(RuntimeWarning, match="matrix is poorly conditioned"):
rbe3 = n2p.formrbe3(uset, 100, 123456, [123, [1, 2, 3, 4, 5]])
regex = re.compile(r"ill\-conditioned matrix", re.IGNORECASE)
with pytest.warns(la.LinAlgWarning, match=regex):
rbe3 = n2p.formrbe3(uset, 100, 123456, [123, [1, 2, 3, 4, 5]])


def test_rbe3_badum():
Expand Down