style: resolve the remaining ruff findings
Some checks failed
CI / lint (pull_request) Has been cancelled
CI / type (pull_request) Has been cancelled
CI / test-headless (macos-latest, 3.10) (pull_request) Has been cancelled
CI / test-headless (macos-latest, 3.11) (pull_request) Has been cancelled
CI / test-headless (macos-latest, 3.12) (pull_request) Has been cancelled
CI / test-headless (ubuntu-latest, 3.10) (pull_request) Has been cancelled
CI / test-headless (ubuntu-latest, 3.11) (pull_request) Has been cancelled
CI / test-headless (ubuntu-latest, 3.12) (pull_request) Has been cancelled
CI / test-headless (windows-latest, 3.10) (pull_request) Has been cancelled
CI / test-headless (windows-latest, 3.11) (pull_request) Has been cancelled
CI / test-headless (windows-latest, 3.12) (pull_request) Has been cancelled
CI / test-gui (pull_request) Has been cancelled
CI / test-integration (macos-latest) (pull_request) Has been cancelled
CI / test-integration (ubuntu-latest) (pull_request) Has been cancelled
CI / test-integration (windows-latest) (pull_request) Has been cancelled
Some checks failed
CI / lint (pull_request) Has been cancelled
CI / type (pull_request) Has been cancelled
CI / test-headless (macos-latest, 3.10) (pull_request) Has been cancelled
CI / test-headless (macos-latest, 3.11) (pull_request) Has been cancelled
CI / test-headless (macos-latest, 3.12) (pull_request) Has been cancelled
CI / test-headless (ubuntu-latest, 3.10) (pull_request) Has been cancelled
CI / test-headless (ubuntu-latest, 3.11) (pull_request) Has been cancelled
CI / test-headless (ubuntu-latest, 3.12) (pull_request) Has been cancelled
CI / test-headless (windows-latest, 3.10) (pull_request) Has been cancelled
CI / test-headless (windows-latest, 3.11) (pull_request) Has been cancelled
CI / test-headless (windows-latest, 3.12) (pull_request) Has been cancelled
CI / test-gui (pull_request) Has been cancelled
CI / test-integration (macos-latest) (pull_request) Has been cancelled
CI / test-integration (ubuntu-latest) (pull_request) Has been cancelled
CI / test-integration (windows-latest) (pull_request) Has been cancelled
Auto-fixes (UP037, UP038, F401, I001, SIM105, RUF100) plus hand-fixes: drop the now-unused `Union` imports, annotate mutable class attributes with ClassVar, raise ValidationError instead of blind Exception in the zero-length test, delete two dead locals, and bind the per-iteration grid-builder closures to their loop variables (B023).
This commit is contained in:
parent
184bb4662b
commit
61b850bf46
126 changed files with 359 additions and 397 deletions
|
|
@ -29,14 +29,6 @@ from otko.commands.grid import (
|
|||
SetCoordSystemsCommand,
|
||||
SetGridSystemCommand,
|
||||
)
|
||||
from otko.commands.series_and_patterns import (
|
||||
AddLoadPatternCommand,
|
||||
AddTimeSeriesCommand,
|
||||
DeleteLoadPatternCommand,
|
||||
DeleteTimeSeriesCommand,
|
||||
UpdateLoadPatternCommand,
|
||||
UpdateTimeSeriesCommand,
|
||||
)
|
||||
from otko.commands.loads import (
|
||||
AddElementLoadsCommand,
|
||||
AddNodalLoadsCommand,
|
||||
|
|
@ -63,6 +55,14 @@ from otko.commands.sections import (
|
|||
DeleteSectionsCommand,
|
||||
UpdateSectionCommand,
|
||||
)
|
||||
from otko.commands.series_and_patterns import (
|
||||
AddLoadPatternCommand,
|
||||
AddTimeSeriesCommand,
|
||||
DeleteLoadPatternCommand,
|
||||
DeleteTimeSeriesCommand,
|
||||
UpdateLoadPatternCommand,
|
||||
UpdateTimeSeriesCommand,
|
||||
)
|
||||
from otko.commands.transforms import (
|
||||
MirrorCommand,
|
||||
MoveNodesCommand,
|
||||
|
|
|
|||
|
|
@ -13,9 +13,7 @@ if TYPE_CHECKING:
|
|||
class AddAnalysisCasesCommand(ProjectCommand):
|
||||
"""Add one or more analysis cases."""
|
||||
|
||||
def __init__(
|
||||
self, vm: "ProjectViewModel", cases: list[Any], *, text: str | None = None
|
||||
) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, cases: list[Any], *, text: str | None = None) -> None:
|
||||
super().__init__(vm, text or f"Add {len(cases)} analysis case(s)")
|
||||
self._cases = list(cases)
|
||||
|
||||
|
|
@ -36,7 +34,7 @@ class AddAnalysisCasesCommand(ProjectCommand):
|
|||
class DeleteAnalysisCasesCommand(ProjectCommand):
|
||||
"""Remove a set of analysis cases."""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", case_ids: set[int]) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, case_ids: set[int]) -> None:
|
||||
super().__init__(vm, f"Delete {len(case_ids)} analysis case(s)")
|
||||
self._case_ids = set(case_ids)
|
||||
self._removed: list[tuple[int, Any]] = []
|
||||
|
|
@ -58,7 +56,7 @@ class DeleteAnalysisCasesCommand(ProjectCommand):
|
|||
class UpdateAnalysisCaseCommand(ProjectCommand):
|
||||
"""Replace an analysis case at a given id."""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", new_case: Any) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, new_case: Any) -> None:
|
||||
super().__init__(vm, f"Edit analysis case {new_case.id}")
|
||||
self._new = new_case
|
||||
self._old: Any | None = None
|
||||
|
|
|
|||
|
|
@ -27,16 +27,16 @@ class ProjectCommand(QUndoCommand):
|
|||
:meth:`_notify` exactly once at the end of each.
|
||||
"""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", text: str) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, text: str) -> None:
|
||||
super().__init__(text)
|
||||
self._vm = vm
|
||||
|
||||
@property
|
||||
def vm(self) -> "ProjectViewModel":
|
||||
def vm(self) -> ProjectViewModel:
|
||||
return self._vm
|
||||
|
||||
@property
|
||||
def project(self) -> "Project":
|
||||
def project(self) -> Project:
|
||||
if self._vm.project is None:
|
||||
raise RuntimeError(f"Cannot apply '{self.text()}': no active project.")
|
||||
return self._vm.project
|
||||
|
|
|
|||
|
|
@ -13,9 +13,7 @@ if TYPE_CHECKING:
|
|||
class AddCombinationsCommand(ProjectCommand):
|
||||
"""Add one or more load combinations."""
|
||||
|
||||
def __init__(
|
||||
self, vm: "ProjectViewModel", combos: list[Any], *, text: str | None = None
|
||||
) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, combos: list[Any], *, text: str | None = None) -> None:
|
||||
super().__init__(vm, text or f"Add {len(combos)} load combination(s)")
|
||||
self._combos = list(combos)
|
||||
|
||||
|
|
@ -36,7 +34,7 @@ class AddCombinationsCommand(ProjectCommand):
|
|||
class DeleteCombinationsCommand(ProjectCommand):
|
||||
"""Remove a set of load combinations."""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", combo_ids: set[int]) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, combo_ids: set[int]) -> None:
|
||||
super().__init__(vm, f"Delete {len(combo_ids)} load combination(s)")
|
||||
self._combo_ids = set(combo_ids)
|
||||
self._removed: list[tuple[int, Any]] = []
|
||||
|
|
@ -60,7 +58,7 @@ class DeleteCombinationsCommand(ProjectCommand):
|
|||
class UpdateCombinationCommand(ProjectCommand):
|
||||
"""Replace a load combination at a given id."""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", new_combo: Any) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, new_combo: Any) -> None:
|
||||
super().__init__(vm, f"Edit load combination {new_combo.id}")
|
||||
self._new = new_combo
|
||||
self._old: Any | None = None
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ if TYPE_CHECKING:
|
|||
class AddEqualDOFConstraintCommand(ProjectCommand):
|
||||
"""Append an ``equalDOF`` constraint to the project (undoable)."""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", constraint: EqualDOFConstraint) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, constraint: EqualDOFConstraint) -> None:
|
||||
super().__init__(
|
||||
vm,
|
||||
f"Add equalDOF {constraint.retained_node}->{constraint.constrained_node}",
|
||||
|
|
@ -48,7 +48,7 @@ class UpdateEqualDOFConstraintCommand(ProjectCommand):
|
|||
"""
|
||||
|
||||
def __init__(
|
||||
self, vm: "ProjectViewModel", index: int, new_constraint: EqualDOFConstraint
|
||||
self, vm: ProjectViewModel, index: int, new_constraint: EqualDOFConstraint
|
||||
) -> None:
|
||||
super().__init__(vm, f"Edit equalDOF row {index + 1}")
|
||||
self._index = index
|
||||
|
|
@ -71,7 +71,7 @@ class UpdateEqualDOFConstraintCommand(ProjectCommand):
|
|||
class DeleteEqualDOFConstraintCommand(ProjectCommand):
|
||||
"""Remove ``equalDOF`` constraints by table-row index (no cascade)."""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", indices: set[int]) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, indices: set[int]) -> None:
|
||||
super().__init__(vm, f"Delete {len(indices)} constraint(s)")
|
||||
self._indices = set(indices)
|
||||
self._removed: list[tuple[int, EqualDOFConstraint]] = []
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class AddElementsCommand(ProjectCommand):
|
|||
"""Add one or more elements in a single undoable step."""
|
||||
|
||||
def __init__(
|
||||
self, vm: "ProjectViewModel", elements: list[Any], *, text: str | None = None
|
||||
self, vm: ProjectViewModel, elements: list[Any], *, text: str | None = None
|
||||
) -> None:
|
||||
super().__init__(vm, text or f"Add {len(elements)} element(s)")
|
||||
self._elements = list(elements)
|
||||
|
|
@ -40,7 +40,7 @@ class AddElementsCommand(ProjectCommand):
|
|||
class DeleteElementsCommand(ProjectCommand):
|
||||
"""Remove a set of elements (no cascade — nodes are not affected)."""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", element_ids: set[int]) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, element_ids: set[int]) -> None:
|
||||
super().__init__(vm, f"Delete {len(element_ids)} element(s)")
|
||||
self._element_ids = set(element_ids)
|
||||
self._removed: list[tuple[int, Any]] = []
|
||||
|
|
@ -68,7 +68,7 @@ class AssignSectionCommand(ProjectCommand):
|
|||
(e.g. trusses, zero-length elements).
|
||||
"""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", element_ids: set[int], section_id: int) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, element_ids: set[int], section_id: int) -> None:
|
||||
super().__init__(vm, f"Assign section {section_id} to {len(element_ids)} element(s)")
|
||||
self._element_ids = set(element_ids)
|
||||
self._section_id = section_id
|
||||
|
|
@ -106,7 +106,7 @@ class ConvertElementTypeCommand(ProjectCommand):
|
|||
|
||||
def __init__(
|
||||
self,
|
||||
vm: "ProjectViewModel",
|
||||
vm: ProjectViewModel,
|
||||
element_ids: set[int],
|
||||
target_type: str,
|
||||
defaults: dict[str, Any] | None = None,
|
||||
|
|
@ -185,7 +185,7 @@ class ReplaceElementsCommand(ProjectCommand):
|
|||
for another while preserving the id and node connectivity.
|
||||
"""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", replacements: list[Any]) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, replacements: list[Any]) -> None:
|
||||
super().__init__(vm, f"Replace {len(replacements)} element(s)")
|
||||
self._replacements = {el.id: el for el in replacements}
|
||||
self._previous: dict[int, Any] = {}
|
||||
|
|
@ -217,7 +217,7 @@ class UpdateElementFieldsCommand(ProjectCommand):
|
|||
|
||||
def __init__(
|
||||
self,
|
||||
vm: "ProjectViewModel",
|
||||
vm: ProjectViewModel,
|
||||
element_id: int,
|
||||
fields: dict[str, Any],
|
||||
) -> None:
|
||||
|
|
@ -254,7 +254,7 @@ class UpdateElementFieldsCommand(ProjectCommand):
|
|||
class AssignMaterialCommand(ProjectCommand):
|
||||
"""Set ``material_id`` on a set of elements (truss-style)."""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", element_ids: set[int], material_id: int) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, element_ids: set[int], material_id: int) -> None:
|
||||
super().__init__(vm, f"Assign material {material_id} to {len(element_ids)} element(s)")
|
||||
self._element_ids = set(element_ids)
|
||||
self._material_id = material_id
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class SetCoordSystemsCommand(ProjectCommand):
|
|||
|
||||
def __init__(
|
||||
self,
|
||||
vm: "ProjectViewModel",
|
||||
vm: ProjectViewModel,
|
||||
new_systems: list[CoordinateGridSystem],
|
||||
) -> None:
|
||||
super().__init__(vm, "Update coordinate/grid systems")
|
||||
|
|
@ -46,7 +46,7 @@ class SetGridSystemCommand(ProjectCommand):
|
|||
systems at once.
|
||||
"""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", new_grid: GridSystem) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, new_grid: GridSystem) -> None:
|
||||
super().__init__(vm, "Update grid system")
|
||||
self._new_grid = new_grid
|
||||
self._previous: GridSystem | None = None
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class AddNodalLoadsCommand(ProjectCommand):
|
|||
|
||||
def __init__(
|
||||
self,
|
||||
vm: "ProjectViewModel",
|
||||
vm: ProjectViewModel,
|
||||
node_ids: set[int],
|
||||
forces: tuple[float, float, float, float, float, float],
|
||||
pattern_id: int | None = None,
|
||||
|
|
@ -122,7 +122,7 @@ class AddElementLoadsCommand(ProjectCommand):
|
|||
|
||||
def __init__(
|
||||
self,
|
||||
vm: "ProjectViewModel",
|
||||
vm: ProjectViewModel,
|
||||
element_ids: set[int],
|
||||
wy: float = 0.0,
|
||||
wz: float = 0.0,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class AddMaterialsCommand(ProjectCommand):
|
|||
"""Add one or more materials in a single undoable step."""
|
||||
|
||||
def __init__(
|
||||
self, vm: "ProjectViewModel", materials: list[Any], *, text: str | None = None
|
||||
self, vm: ProjectViewModel, materials: list[Any], *, text: str | None = None
|
||||
) -> None:
|
||||
super().__init__(vm, text or f"Add {len(materials)} material(s)")
|
||||
self._materials = list(materials)
|
||||
|
|
@ -36,7 +36,7 @@ class AddMaterialsCommand(ProjectCommand):
|
|||
class DeleteMaterialsCommand(ProjectCommand):
|
||||
"""Remove materials (no cascade)."""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", material_ids: set[int]) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, material_ids: set[int]) -> None:
|
||||
super().__init__(vm, f"Delete {len(material_ids)} material(s)")
|
||||
self._material_ids = set(material_ids)
|
||||
self._removed: list[tuple[int, Any]] = []
|
||||
|
|
@ -64,7 +64,7 @@ class UpdateMaterialCommand(ProjectCommand):
|
|||
otherwise this is an Add+Delete, not an update.
|
||||
"""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", new_material: Any) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, new_material: Any) -> None:
|
||||
super().__init__(vm, f"Edit material {new_material.id}")
|
||||
self._new = new_material
|
||||
self._old: Any | None = None
|
||||
|
|
|
|||
|
|
@ -14,9 +14,7 @@ if TYPE_CHECKING:
|
|||
class AddNodesCommand(ProjectCommand):
|
||||
"""Add one or more nodes in a single undoable step."""
|
||||
|
||||
def __init__(
|
||||
self, vm: "ProjectViewModel", nodes: list[Node], *, text: str | None = None
|
||||
) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, nodes: list[Node], *, text: str | None = None) -> None:
|
||||
super().__init__(vm, text or f"Add {len(nodes)} node(s)")
|
||||
self._nodes = list(nodes)
|
||||
|
||||
|
|
@ -41,7 +39,7 @@ class DeleteNodesCommand(ProjectCommand):
|
|||
them in their original positions.
|
||||
"""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", node_ids: set[int]) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, node_ids: set[int]) -> None:
|
||||
super().__init__(vm, f"Delete {len(node_ids)} node(s)")
|
||||
self._node_ids = set(node_ids)
|
||||
self._removed_nodes: list[tuple[int, Node]] = [] # (index, node)
|
||||
|
|
@ -95,7 +93,7 @@ class SetRestraintCommand(ProjectCommand):
|
|||
|
||||
def __init__(
|
||||
self,
|
||||
vm: "ProjectViewModel",
|
||||
vm: ProjectViewModel,
|
||||
node_ids: set[int],
|
||||
restraint: tuple[bool, bool, bool, bool, bool, bool],
|
||||
) -> None:
|
||||
|
|
@ -130,7 +128,7 @@ class UpdateNodeFieldsCommand(ProjectCommand):
|
|||
|
||||
def __init__(
|
||||
self,
|
||||
vm: "ProjectViewModel",
|
||||
vm: ProjectViewModel,
|
||||
node_id: int,
|
||||
fields: dict[str, Any],
|
||||
) -> None:
|
||||
|
|
@ -168,7 +166,7 @@ class SetMassCommand(ProjectCommand):
|
|||
|
||||
def __init__(
|
||||
self,
|
||||
vm: "ProjectViewModel",
|
||||
vm: ProjectViewModel,
|
||||
node_ids: set[int],
|
||||
mass: tuple[float, float, float, float, float, float],
|
||||
) -> None:
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class SetUnitsCommand(ProjectCommand):
|
|||
so both redo and undo notify (dirty + modelMutated) to refresh.
|
||||
"""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", units: UnitSystem) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, units: UnitSystem) -> None:
|
||||
super().__init__(vm, f"Set display units to {units.value}")
|
||||
self._units = units
|
||||
self._previous: UnitSystem | None = None
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class AddSectionsCommand(ProjectCommand):
|
|||
"""Add one or more sections in a single undoable step."""
|
||||
|
||||
def __init__(
|
||||
self, vm: "ProjectViewModel", sections: list[Any], *, text: str | None = None
|
||||
self, vm: ProjectViewModel, sections: list[Any], *, text: str | None = None
|
||||
) -> None:
|
||||
super().__init__(vm, text or f"Add {len(sections)} section(s)")
|
||||
self._sections = list(sections)
|
||||
|
|
@ -36,7 +36,7 @@ class AddSectionsCommand(ProjectCommand):
|
|||
class DeleteSectionsCommand(ProjectCommand):
|
||||
"""Remove sections (no cascade — elements referencing them must be cleaned separately)."""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", section_ids: set[int]) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, section_ids: set[int]) -> None:
|
||||
super().__init__(vm, f"Delete {len(section_ids)} section(s)")
|
||||
self._section_ids = set(section_ids)
|
||||
self._removed: list[tuple[int, Any]] = []
|
||||
|
|
@ -60,7 +60,7 @@ class DeleteSectionsCommand(ProjectCommand):
|
|||
class UpdateSectionCommand(ProjectCommand):
|
||||
"""Replace a section's parameters at a given id."""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", new_section: Any) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, new_section: Any) -> None:
|
||||
super().__init__(vm, f"Edit section {new_section.id}")
|
||||
self._new = new_section
|
||||
self._old: Any | None = None
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ if TYPE_CHECKING:
|
|||
class AddTimeSeriesCommand(ProjectCommand):
|
||||
"""Append a :class:`TimeSeries` to the project (undoable)."""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", ts: "TimeSeries") -> None:
|
||||
def __init__(self, vm: ProjectViewModel, ts: TimeSeries) -> None:
|
||||
super().__init__(vm, f"Add time series '{ts.name or ts.id}'")
|
||||
self._ts = ts
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ class UpdateTimeSeriesCommand(ProjectCommand):
|
|||
The new series must carry the same id as the one being replaced.
|
||||
"""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", new_ts: Any) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, new_ts: Any) -> None:
|
||||
super().__init__(vm, f"Edit time series {new_ts.id}")
|
||||
self._new = new_ts
|
||||
self._old: Any | None = None
|
||||
|
|
@ -67,7 +67,7 @@ class DeleteTimeSeriesCommand(ProjectCommand):
|
|||
"""Remove time series (no cascade — patterns referencing them must be
|
||||
cleaned separately; ``validate_references`` catches strays before save)."""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", ts_ids: set[int]) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, ts_ids: set[int]) -> None:
|
||||
super().__init__(vm, f"Delete {len(ts_ids)} time serie(s)")
|
||||
self._ts_ids = set(ts_ids)
|
||||
self._removed: list[tuple[int, Any]] = []
|
||||
|
|
@ -91,7 +91,7 @@ class DeleteTimeSeriesCommand(ProjectCommand):
|
|||
class AddLoadPatternCommand(ProjectCommand):
|
||||
"""Append a :class:`LoadPattern` to the project (undoable)."""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", pattern: "LoadPattern") -> None:
|
||||
def __init__(self, vm: ProjectViewModel, pattern: LoadPattern) -> None:
|
||||
super().__init__(vm, f"Add pattern '{pattern.name or pattern.id}'")
|
||||
self._pattern = pattern
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ class UpdateLoadPatternCommand(ProjectCommand):
|
|||
drops the pattern's stored loads.
|
||||
"""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", new_pattern: Any) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, new_pattern: Any) -> None:
|
||||
super().__init__(vm, f"Edit pattern {new_pattern.id}")
|
||||
self._new = new_pattern
|
||||
self._old: Any | None = None
|
||||
|
|
@ -142,7 +142,7 @@ class UpdateLoadPatternCommand(ProjectCommand):
|
|||
class DeleteLoadPatternCommand(ProjectCommand):
|
||||
"""Remove load patterns (their child nodal/element loads go with them)."""
|
||||
|
||||
def __init__(self, vm: "ProjectViewModel", pattern_ids: set[int]) -> None:
|
||||
def __init__(self, vm: ProjectViewModel, pattern_ids: set[int]) -> None:
|
||||
super().__init__(vm, f"Delete {len(pattern_ids)} pattern(s)")
|
||||
self._pattern_ids = set(pattern_ids)
|
||||
self._removed: list[tuple[int, Any]] = []
|
||||
|
|
|
|||
|
|
@ -15,10 +15,9 @@ All copies inherit the source node's restraint, mass, and name.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, Any, Literal
|
||||
from typing import TYPE_CHECKING, Literal
|
||||
|
||||
from otko.commands.base import ProjectCommand
|
||||
from otko.core import Node
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from otko.viewmodels import ProjectViewModel
|
||||
|
|
@ -30,7 +29,7 @@ class MoveNodesCommand(ProjectCommand):
|
|||
|
||||
def __init__(
|
||||
self,
|
||||
vm: "ProjectViewModel",
|
||||
vm: ProjectViewModel,
|
||||
node_ids: set[int],
|
||||
offset: tuple[float, float, float],
|
||||
) -> None:
|
||||
|
|
@ -63,7 +62,7 @@ class ReplicateCommand(ProjectCommand):
|
|||
|
||||
def __init__(
|
||||
self,
|
||||
vm: "ProjectViewModel",
|
||||
vm: ProjectViewModel,
|
||||
node_ids: set[int],
|
||||
element_ids: set[int],
|
||||
offset: tuple[float, float, float],
|
||||
|
|
@ -147,7 +146,7 @@ class MirrorCommand(ProjectCommand):
|
|||
|
||||
def __init__(
|
||||
self,
|
||||
vm: "ProjectViewModel",
|
||||
vm: ProjectViewModel,
|
||||
node_ids: set[int],
|
||||
element_ids: set[int],
|
||||
plane: Plane,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ in Phase 6/8.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Annotated, Literal, Union
|
||||
from typing import Annotated, Literal
|
||||
|
||||
from pydantic import Field, PositiveFloat, PositiveInt, model_validator
|
||||
|
||||
|
|
@ -269,6 +269,6 @@ class ResponseSpectrumCase(Entity):
|
|||
|
||||
|
||||
AnalysisCase = Annotated[
|
||||
Union[StaticCase, ModalCase, TransientCase, PushoverCase, ResponseSpectrumCase],
|
||||
StaticCase | ModalCase | TransientCase | PushoverCase | ResponseSpectrumCase,
|
||||
Field(discriminator="type"),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ Conventions follow OpenSeesPy ``element ...`` commands.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Annotated, Literal, Union
|
||||
from typing import Annotated, Literal
|
||||
|
||||
from pydantic import Field, PositiveFloat, PositiveInt
|
||||
|
||||
|
|
@ -198,16 +198,14 @@ class QuadElement(Entity):
|
|||
|
||||
|
||||
Element = Annotated[
|
||||
Union[
|
||||
TrussElement,
|
||||
CorotTrussElement,
|
||||
ElasticBeamColumn,
|
||||
ForceBeamColumn,
|
||||
DispBeamColumn,
|
||||
ZeroLengthElement,
|
||||
ZeroLengthSectionElement,
|
||||
BeamWithHingesElement,
|
||||
QuadElement,
|
||||
],
|
||||
TrussElement
|
||||
| CorotTrussElement
|
||||
| ElasticBeamColumn
|
||||
| ForceBeamColumn
|
||||
| DispBeamColumn
|
||||
| ZeroLengthElement
|
||||
| ZeroLengthSectionElement
|
||||
| BeamWithHingesElement
|
||||
| QuadElement,
|
||||
Field(discriminator="type"),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ class GridSystem(BaseModel):
|
|||
return data
|
||||
|
||||
@model_validator(mode="after")
|
||||
def _sort_and_dedupe(self) -> "GridSystem":
|
||||
def _sort_and_dedupe(self) -> GridSystem:
|
||||
for name in ("x_grid_lines", "y_grid_lines", "z_grid_lines"):
|
||||
lines: list[GridLine] = list(getattr(self, name))
|
||||
lines.sort(key=lambda ln: ln.ordinate)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ pattern is deleted, its loads go with it.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Annotated, Literal, Union
|
||||
from typing import Annotated, Literal
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field, PositiveInt, model_validator
|
||||
|
||||
|
|
@ -110,7 +110,7 @@ class ResponseSpectrum(Entity):
|
|||
|
||||
|
||||
TimeSeries = Annotated[
|
||||
Union[LinearTimeSeries, ConstantTimeSeries, PathTimeSeries],
|
||||
LinearTimeSeries | ConstantTimeSeries | PathTimeSeries,
|
||||
Field(discriminator="type"),
|
||||
]
|
||||
|
||||
|
|
@ -229,7 +229,7 @@ class LoadCombination(Entity):
|
|||
)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def _check_items(self) -> "LoadCombination":
|
||||
def _check_items(self) -> LoadCombination:
|
||||
"""Reject duplicate case ids and non-finite factors."""
|
||||
import math
|
||||
|
||||
|
|
@ -250,6 +250,6 @@ class LoadCombination(Entity):
|
|||
|
||||
|
||||
LoadPattern = Annotated[
|
||||
Union[PlainLoadPattern, UniformExcitationPattern, ImposedSupportMotionPattern],
|
||||
PlainLoadPattern | UniformExcitationPattern | ImposedSupportMotionPattern,
|
||||
Field(discriminator="type"),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ https://openseespydoc.readthedocs.io/en/latest/src/uniaxialMaterial.html
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Annotated, Literal, Union
|
||||
from typing import Annotated, Literal
|
||||
|
||||
from pydantic import Field, PositiveFloat, model_validator
|
||||
|
||||
|
|
@ -130,7 +130,7 @@ class Concrete04(Entity):
|
|||
)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def _tensile_params_consistent(self) -> "Concrete04":
|
||||
def _tensile_params_consistent(self) -> Concrete04:
|
||||
if self.fct is not None and self.et is None:
|
||||
raise ValueError("et is required when fct is given.")
|
||||
if self.et is not None and self.fct is None:
|
||||
|
|
@ -229,18 +229,16 @@ class HystereticSM(Entity):
|
|||
|
||||
# ──────────────────────────── Discriminated union ────────────────────────────
|
||||
Material = Annotated[
|
||||
Union[
|
||||
ElasticIsotropic,
|
||||
ElasticUniaxial,
|
||||
Steel01,
|
||||
Steel02,
|
||||
Concrete01,
|
||||
Concrete02,
|
||||
Concrete04,
|
||||
ElasticPP,
|
||||
HystereticMaterial,
|
||||
HystereticSM,
|
||||
],
|
||||
ElasticIsotropic
|
||||
| ElasticUniaxial
|
||||
| Steel01
|
||||
| Steel02
|
||||
| Concrete01
|
||||
| Concrete02
|
||||
| Concrete04
|
||||
| ElasticPP
|
||||
| HystereticMaterial
|
||||
| HystereticSM,
|
||||
Field(discriminator="type"),
|
||||
]
|
||||
"""Tagged union of every material kind. Pydantic uses ``type`` to dispatch on JSON load."""
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ class Project(BaseModel):
|
|||
return data
|
||||
|
||||
@model_validator(mode="after")
|
||||
def _ensure_global_system(self) -> "Project":
|
||||
def _ensure_global_system(self) -> Project:
|
||||
"""Guarantee that a 'Global' entry exists as the first coord system."""
|
||||
has_global = any(cs.name == "Global" for cs in self.coord_systems)
|
||||
if not has_global:
|
||||
|
|
@ -174,7 +174,7 @@ class Project(BaseModel):
|
|||
return self
|
||||
|
||||
@model_validator(mode="after")
|
||||
def _ensure_indexed(self) -> "Project":
|
||||
def _ensure_indexed(self) -> Project:
|
||||
"""Wrap every collection in an :class:`_IndexedList` and drop caches.
|
||||
|
||||
Runs after each validation pass (construction, ``model_validate``,
|
||||
|
|
@ -223,7 +223,7 @@ class Project(BaseModel):
|
|||
|
||||
# ─────────────────── invariants ───────────────────
|
||||
@model_validator(mode="after")
|
||||
def _check_ndm_ndf(self) -> "Project":
|
||||
def _check_ndm_ndf(self) -> Project:
|
||||
valid = {(2, 2), (2, 3), (3, 3), (3, 6)}
|
||||
if (self.ndm, self.ndf) not in valid:
|
||||
raise ValueError(
|
||||
|
|
@ -233,7 +233,7 @@ class Project(BaseModel):
|
|||
return self
|
||||
|
||||
@model_validator(mode="after")
|
||||
def _check_unique_ids(self) -> "Project":
|
||||
def _check_unique_ids(self) -> Project:
|
||||
for label, items in (
|
||||
("node", self.nodes),
|
||||
("material", self.materials),
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ exactly so the runner can emit them without further translation.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Annotated, Literal, Union
|
||||
from typing import Annotated, Literal
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field, PositiveFloat, PositiveInt
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ class RectShape(BaseModel):
|
|||
|
||||
|
||||
SectionShape = Annotated[
|
||||
Union[PipeShape, AngleShape, RectShape],
|
||||
PipeShape | AngleShape | RectShape,
|
||||
Field(discriminator="kind"),
|
||||
]
|
||||
|
||||
|
|
@ -165,12 +165,12 @@ class StraightLayer(BaseModel):
|
|||
|
||||
|
||||
Patch = Annotated[
|
||||
Union[RectangularPatch, CircularPatch],
|
||||
RectangularPatch | CircularPatch,
|
||||
Field(discriminator="kind"),
|
||||
]
|
||||
|
||||
Layer = Annotated[
|
||||
Union[StraightLayer],
|
||||
StraightLayer,
|
||||
Field(discriminator="kind"),
|
||||
]
|
||||
|
||||
|
|
@ -225,6 +225,6 @@ class SectionAggregator(Entity):
|
|||
|
||||
|
||||
Section = Annotated[
|
||||
Union[ElasticSection, FiberSection, SectionAggregator],
|
||||
ElasticSection | FiberSection | SectionAggregator,
|
||||
Field(discriminator="type"),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -12,8 +12,9 @@ the main thread.
|
|||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable
|
||||
from typing import Any
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ def _record_calls(project: Project, case_id: int | None) -> list[RecordedCall]:
|
|||
runner.build()
|
||||
else:
|
||||
case = _find_case(project, case_id)
|
||||
if isinstance(case, (StaticCase, ModalCase, PushoverCase)):
|
||||
if isinstance(case, StaticCase | ModalCase | PushoverCase):
|
||||
# Safe to run end-to-end: dummy query results let the
|
||||
# harvesting code finish; queries are filtered at render.
|
||||
runner.run(case)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ building the PathTimeSeries.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
|
|
@ -64,10 +65,9 @@ def parse_peer_record(path: str | Path) -> tuple[float, int, list[float]]:
|
|||
values: list[float] = []
|
||||
for line in lines[data_start:]:
|
||||
for tok in line.split():
|
||||
try:
|
||||
# Skip stray non-numeric tokens.
|
||||
with contextlib.suppress(ValueError):
|
||||
values.append(float(tok))
|
||||
except ValueError:
|
||||
pass # skip stray tokens
|
||||
if not values:
|
||||
raise ValueError("Header parsed but no numeric data lines found.")
|
||||
return dt, npts, values
|
||||
|
|
@ -83,10 +83,8 @@ def parse_plain_values(path: str | Path) -> list[float]:
|
|||
vals: list[float] = []
|
||||
for line in text.splitlines():
|
||||
for tok in line.split():
|
||||
try:
|
||||
with contextlib.suppress(ValueError):
|
||||
vals.append(float(tok))
|
||||
except ValueError:
|
||||
pass
|
||||
if not vals:
|
||||
raise ValueError(f"{path} contains no numeric values.")
|
||||
return vals
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ def _angle_in_arc(angle: float, start: float, span: float) -> bool:
|
|||
|
||||
def bbox_for_section(
|
||||
section: object,
|
||||
project: "Project | None" = None,
|
||||
project: Project | None = None,
|
||||
) -> tuple[float, float] | None:
|
||||
"""Return ``(width_y, height_z)`` of the section's local bounding box.
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ import numpy as np
|
|||
from otko.core.sections import (
|
||||
CircularPatch,
|
||||
FiberSection,
|
||||
Fibre,
|
||||
RectangularPatch,
|
||||
StraightLayer,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ a re-paint without losing camera/selection state.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
from pathlib import Path
|
||||
|
||||
from PySide6.QtCore import QObject, Signal, Slot
|
||||
|
|
@ -40,10 +41,8 @@ class ProjectViewModel(QObject):
|
|||
@Slot(bool)
|
||||
def _on_stack_clean_changed(self, clean: bool) -> None:
|
||||
# Guard against the late-fire that Qt sends during destruction.
|
||||
try:
|
||||
with contextlib.suppress(RuntimeError):
|
||||
self._set_dirty(not clean)
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
# ── read ─────────────────────────────────────────────────────────
|
||||
@property
|
||||
|
|
|
|||
|
|
@ -47,9 +47,9 @@ from otko.views.dialogs import (
|
|||
AssignSectionDialog,
|
||||
AssignSupportDialog,
|
||||
AssignZeroLengthSectionDialog,
|
||||
LoadCombinationManagerDialog,
|
||||
CoordinateGridSystemsDialog,
|
||||
LinearTimeSeriesDialog,
|
||||
LoadCombinationManagerDialog,
|
||||
MaterialLibraryDialog,
|
||||
MaterialTesterDialog,
|
||||
MirrorDialog,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ Convention:
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
|
|
@ -254,10 +255,8 @@ class DiagramRenderer:
|
|||
pass
|
||||
self._actor = None
|
||||
if self._label_actor is not None:
|
||||
try:
|
||||
with contextlib.suppress(Exception):
|
||||
self._plotter.remove_actor(self._label_actor, render=False)
|
||||
except Exception:
|
||||
pass
|
||||
self._label_actor = None
|
||||
|
||||
# ── helpers ─────────────────────────────────────────────────────
|
||||
|
|
|
|||
|
|
@ -10,9 +10,10 @@ Mode-aware: MODEL / DEFORMED / MODAL change only the points array.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import enum
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
from typing import Any, ClassVar
|
||||
|
||||
import numpy as np
|
||||
import pyvista as pv
|
||||
|
|
@ -24,11 +25,11 @@ from otko.core import (
|
|||
ElasticBeamColumn,
|
||||
ForceBeamColumn,
|
||||
NodalLoad,
|
||||
QuadElement,
|
||||
UniformElementLoad,
|
||||
PlainLoadPattern,
|
||||
Project,
|
||||
QuadElement,
|
||||
TrussElement,
|
||||
UniformElementLoad,
|
||||
ZeroLengthElement,
|
||||
ZeroLengthSectionElement,
|
||||
)
|
||||
|
|
@ -184,8 +185,8 @@ class ModelRenderer:
|
|||
r, g, b = (int(round(x * 255)) for x in rgb)
|
||||
return f"#{r:02x}{g:02x}{b:02x}"
|
||||
|
||||
_NODE_LUT = ["#d9d9d9", "#00ffff"] # gray normal, cyan selected
|
||||
_FRAME_LUT = ["#338cd9", "#00ffff"] # blue normal, cyan selected
|
||||
_NODE_LUT: ClassVar[list[str]] = ["#d9d9d9", "#00ffff"] # gray normal, cyan selected
|
||||
_FRAME_LUT: ClassVar[list[str]] = ["#338cd9", "#00ffff"] # blue normal, cyan selected
|
||||
|
||||
def __init__(self, plotter: Any, style: RenderStyle | None = None) -> None:
|
||||
self._plotter = plotter
|
||||
|
|
@ -219,10 +220,8 @@ class ModelRenderer:
|
|||
# plan view at Z=3 doesn't see the Z=0 grid cluttering the view.
|
||||
self._working_plane: tuple[str, float] | None = None
|
||||
|
||||
try:
|
||||
with contextlib.suppress(Exception):
|
||||
self._plotter.enable_anti_aliasing("ssaa")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# ── public API ───────────────────────────────────────────────────
|
||||
def render(self, project: Project | None) -> None:
|
||||
|
|
@ -329,10 +328,8 @@ class ModelRenderer:
|
|||
"""
|
||||
# Remove any previous marker.
|
||||
if self._hover_actor is not None:
|
||||
try:
|
||||
with contextlib.suppress(Exception):
|
||||
self._plotter.remove_actor(self._hover_actor, render=False)
|
||||
except Exception:
|
||||
pass
|
||||
self._hover_actor = None
|
||||
|
||||
if world_point is None:
|
||||
|
|
@ -376,10 +373,8 @@ class ModelRenderer:
|
|||
sphere = pv.Sphere(radius=radius, theta_resolution=8, phi_resolution=8)
|
||||
glyph = self._node_pd.glyph(geom=sphere, scale=False, orient=False)
|
||||
if self._node_actor is not None:
|
||||
try:
|
||||
with contextlib.suppress(Exception):
|
||||
self._plotter.remove_actor(self._node_actor, render=False)
|
||||
except Exception:
|
||||
pass
|
||||
self._node_glyph = glyph
|
||||
self._node_actor = self._plotter.add_mesh(
|
||||
glyph,
|
||||
|
|
@ -484,10 +479,17 @@ class ModelRenderer:
|
|||
plane_axis = axis_idx
|
||||
plane_offset_local = plane_off - cs_shift
|
||||
|
||||
def _on_active_plane(local_pt: tuple[float, float, float]) -> bool:
|
||||
if plane_axis is None:
|
||||
# Bind the per-iteration plane state as defaults so the closure
|
||||
# cannot read a later iteration's values (B023); the helper is
|
||||
# only ever called from within this loop body.
|
||||
def _on_active_plane(
|
||||
local_pt: tuple[float, float, float],
|
||||
_axis: int | None = plane_axis,
|
||||
_offset: float | None = plane_offset_local,
|
||||
) -> bool:
|
||||
if _axis is None or _offset is None:
|
||||
return True
|
||||
return abs(local_pt[plane_axis] - plane_offset_local) < 1e-6 # type: ignore[operator]
|
||||
return abs(local_pt[_axis] - _offset) < 1e-6
|
||||
|
||||
# Collect active + dim segments separately so they get their
|
||||
# own polydata + actor (different opacity / color).
|
||||
|
|
@ -496,13 +498,21 @@ class ModelRenderer:
|
|||
dim_pts: list[tuple[float, float, float]] = []
|
||||
dim_cells: list[int] = []
|
||||
|
||||
def add_seg(p1: tuple[float, float, float], p2: tuple[float, float, float]) -> None:
|
||||
def add_seg(
|
||||
p1: tuple[float, float, float],
|
||||
p2: tuple[float, float, float],
|
||||
_active_pts: list[tuple[float, float, float]] = active_pts,
|
||||
_active_cells: list[int] = active_cells,
|
||||
_dim_pts: list[tuple[float, float, float]] = dim_pts,
|
||||
_dim_cells: list[int] = dim_cells,
|
||||
_cs: Any = cs,
|
||||
) -> None:
|
||||
on_active = _on_active_plane(p1) and _on_active_plane(p2)
|
||||
bucket_pts = active_pts if on_active else dim_pts
|
||||
bucket_cells = active_cells if on_active else dim_cells
|
||||
bucket_pts = _active_pts if on_active else _dim_pts
|
||||
bucket_cells = _active_cells if on_active else _dim_cells
|
||||
i = len(bucket_pts)
|
||||
bucket_pts.append(cs.coord.local_to_world(p1))
|
||||
bucket_pts.append(cs.coord.local_to_world(p2))
|
||||
bucket_pts.append(_cs.coord.local_to_world(p1))
|
||||
bucket_pts.append(_cs.coord.local_to_world(p2))
|
||||
bucket_cells.extend([2, i, i + 1])
|
||||
|
||||
z_planes = zs if zs else [0.0]
|
||||
|
|
@ -614,7 +624,7 @@ class ModelRenderer:
|
|||
continue
|
||||
# By design: area-only / thickness-only / material-only
|
||||
# elements carry no section.
|
||||
if isinstance(el, (TrussElement, CorotTrussElement, QuadElement, ZeroLengthElement)):
|
||||
if isinstance(el, TrussElement | CorotTrussElement | QuadElement | ZeroLengthElement):
|
||||
continue
|
||||
node_i = node_by_id.get(el.nodes[0])
|
||||
node_j = node_by_id.get(el.nodes[1])
|
||||
|
|
@ -665,18 +675,16 @@ class ModelRenderer:
|
|||
diag = self._diag_of_points(self._node_original_points)
|
||||
cap = max(diag * 0.08, 1e-6)
|
||||
for el in project.elements:
|
||||
if isinstance(el, (QuadElement, ZeroLengthElement, ZeroLengthSectionElement)):
|
||||
if isinstance(el, QuadElement | ZeroLengthElement | ZeroLengthSectionElement):
|
||||
continue
|
||||
if not isinstance(
|
||||
el,
|
||||
(
|
||||
ElasticBeamColumn,
|
||||
DispBeamColumn,
|
||||
ForceBeamColumn,
|
||||
BeamWithHingesElement,
|
||||
TrussElement,
|
||||
CorotTrussElement,
|
||||
),
|
||||
ElasticBeamColumn
|
||||
| DispBeamColumn
|
||||
| ForceBeamColumn
|
||||
| BeamWithHingesElement
|
||||
| TrussElement
|
||||
| CorotTrussElement,
|
||||
):
|
||||
continue
|
||||
node_i = node_by_id.get(el.nodes[0])
|
||||
|
|
@ -1094,15 +1102,11 @@ class ModelRenderer:
|
|||
self._clear_label_actors()
|
||||
for a in (self._node_actor, self._frame_actor):
|
||||
if a is not None:
|
||||
try:
|
||||
with contextlib.suppress(Exception):
|
||||
self._plotter.remove_actor(a, render=False)
|
||||
except Exception:
|
||||
pass
|
||||
for a in self._aux_actors:
|
||||
try:
|
||||
with contextlib.suppress(Exception):
|
||||
self._plotter.remove_actor(a, render=False)
|
||||
except Exception:
|
||||
pass
|
||||
self._node_actor = None
|
||||
self._frame_actor = None
|
||||
self._aux_actors.clear()
|
||||
|
|
@ -1120,10 +1124,8 @@ class ModelRenderer:
|
|||
def _clear_label_actors(self) -> None:
|
||||
for actor in (self._node_label_actor, self._element_label_actor):
|
||||
if actor is not None:
|
||||
try:
|
||||
with contextlib.suppress(Exception):
|
||||
self._plotter.remove_actor(actor, render=False)
|
||||
except Exception:
|
||||
pass
|
||||
self._node_label_actor = None
|
||||
self._element_label_actor = None
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ from PySide6.QtWidgets import (
|
|||
QDialogButtonBox,
|
||||
QDoubleSpinBox,
|
||||
QFormLayout,
|
||||
QInputDialog,
|
||||
QLabel,
|
||||
QLineEdit,
|
||||
QVBoxLayout,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ it maps cleanly onto our existing :class:`SetMassCommand`.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
|
||||
from PySide6.QtWidgets import (
|
||||
QCheckBox,
|
||||
QDialog,
|
||||
|
|
@ -103,10 +105,8 @@ class AssignMassesDialog(QDialog):
|
|||
self._my.setValue(self._mx.value())
|
||||
self._mx.valueChanged.connect(self._my.setValue)
|
||||
else:
|
||||
try:
|
||||
with contextlib.suppress(RuntimeError, TypeError):
|
||||
self._mx.valueChanged.disconnect(self._my.setValue)
|
||||
except (RuntimeError, TypeError):
|
||||
pass
|
||||
|
||||
def mass_vector(self) -> tuple[float, float, float, float, float, float]:
|
||||
"""Return the 6-tuple (Mx, My, Mz, Mxx, Myy, Mzz)."""
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ model's actual ``ndf`` at translation time.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtWidgets import (
|
||||
QButtonGroup,
|
||||
QCheckBox,
|
||||
|
|
@ -22,7 +21,6 @@ from PySide6.QtWidgets import (
|
|||
QWidget,
|
||||
)
|
||||
|
||||
|
||||
# Preset → 6-tuple (Ux, Uy, Uz, Rx, Ry, Rz)
|
||||
PRESETS: dict[str, tuple[bool, bool, bool, bool, bool, bool]] = {
|
||||
"Free": (False, False, False, False, False, False),
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ from PySide6.QtWidgets import (
|
|||
QListWidget,
|
||||
QListWidgetItem,
|
||||
QSpinBox,
|
||||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ from __future__ import annotations
|
|||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from pydantic import ValidationError
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtWidgets import (
|
||||
QDialog,
|
||||
|
|
@ -19,7 +20,6 @@ from PySide6.QtWidgets import (
|
|||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
from pydantic import ValidationError
|
||||
|
||||
from otko.commands import (
|
||||
AddAnalysisCasesCommand,
|
||||
|
|
@ -34,7 +34,7 @@ from otko.core import (
|
|||
TransientCase,
|
||||
)
|
||||
from otko.viewmodels import ProjectViewModel
|
||||
from otko.views.dialogs.case_forms import FORM_REGISTRY, form_for
|
||||
from otko.views.dialogs.case_forms import form_for
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from otko.core import Project
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ Top-level controls:
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import ClassVar
|
||||
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtGui import QColor
|
||||
from PySide6.QtWidgets import (
|
||||
|
|
@ -27,7 +29,6 @@ from PySide6.QtWidgets import (
|
|||
QComboBox,
|
||||
QDialog,
|
||||
QDialogButtonBox,
|
||||
QDoubleSpinBox,
|
||||
QFormLayout,
|
||||
QGroupBox,
|
||||
QHBoxLayout,
|
||||
|
|
@ -52,7 +53,6 @@ from otko.core.geometry import (
|
|||
GridSystem,
|
||||
)
|
||||
|
||||
|
||||
_LINE_TYPE_CHOICES = ["Primary", "Secondary"]
|
||||
_BUBBLE_LOC_CHOICES = ["Start", "End"]
|
||||
|
||||
|
|
@ -60,7 +60,14 @@ _BUBBLE_LOC_CHOICES = ["Start", "End"]
|
|||
class _AxisGridTable(QWidget):
|
||||
"""A single X/Y/Z spreadsheet — one row per GridLine."""
|
||||
|
||||
COLUMNS = ["Grid ID", "Ordinate", "Line Type", "Visibility", "Bubble Loc", "Color"]
|
||||
COLUMNS: ClassVar[list[str]] = [
|
||||
"Grid ID",
|
||||
"Ordinate",
|
||||
"Line Type",
|
||||
"Visibility",
|
||||
"Bubble Loc",
|
||||
"Color",
|
||||
]
|
||||
|
||||
def __init__(self, axis: str, parent: QWidget | None = None) -> None:
|
||||
super().__init__(parent)
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ from PySide6.QtWidgets import (
|
|||
QDialog,
|
||||
QDialogButtonBox,
|
||||
QFormLayout,
|
||||
QLineEdit,
|
||||
QLabel,
|
||||
QLineEdit,
|
||||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ from PySide6.QtWidgets import (
|
|||
QDoubleSpinBox,
|
||||
QFormLayout,
|
||||
QGroupBox,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QVBoxLayout,
|
||||
QWidget,
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ committed. Each Add/Edit/Delete is its own undoable step.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from pydantic import ValidationError
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtWidgets import (
|
||||
QComboBox,
|
||||
QDialog,
|
||||
QDialogButtonBox,
|
||||
QHBoxLayout,
|
||||
|
|
@ -23,7 +23,6 @@ from PySide6.QtWidgets import (
|
|||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
from pydantic import ValidationError
|
||||
|
||||
from otko.commands import (
|
||||
AddMaterialsCommand,
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ class PathTimeSeriesDialog(QDialog):
|
|||
return
|
||||
try:
|
||||
dt, npts, vals = parse_peer_record(fname)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
except Exception as exc:
|
||||
QMessageBox.critical(self, "PEER import failed", str(exc))
|
||||
return
|
||||
self._values = vals
|
||||
|
|
@ -142,7 +142,7 @@ class PathTimeSeriesDialog(QDialog):
|
|||
return
|
||||
try:
|
||||
vals = parse_plain_values(fname)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
except Exception as exc:
|
||||
QMessageBox.critical(self, "Import failed", str(exc))
|
||||
return
|
||||
self._values = vals
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ from PySide6.QtWidgets import (
|
|||
QDialog,
|
||||
QDialogButtonBox,
|
||||
QDoubleSpinBox,
|
||||
QFormLayout,
|
||||
QGroupBox,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ class RunAnalysisDialog(QDialog):
|
|||
results_dir = self._vm.path.parent / f"{self._vm.path.stem}_results"
|
||||
try:
|
||||
self._runner.run(self._vm.project, case, results_dir=results_dir)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
except Exception as exc:
|
||||
self._log.appendPlainText(f"Could not start: {exc}")
|
||||
|
||||
def _on_evaluate_combo(self) -> None:
|
||||
|
|
@ -233,7 +233,7 @@ class RunAnalysisDialog(QDialog):
|
|||
self._results = combined
|
||||
self._log.appendPlainText(f"--- Done. Returned {type(combined).__name__}. ---")
|
||||
self._runner.finished.emit(combined)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
except Exception as exc:
|
||||
import traceback
|
||||
|
||||
self._log.appendPlainText("--- FAILED ---")
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ from __future__ import annotations
|
|||
|
||||
from typing import Any
|
||||
|
||||
import numpy as np
|
||||
import pyqtgraph as pg
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtWidgets import (
|
||||
|
|
@ -324,7 +323,6 @@ class FiberSectionEditor(QDialog):
|
|||
self._props_label.setText("Add patches or layers to see the preview.")
|
||||
return
|
||||
|
||||
f = props.fibre_yz
|
||||
# Color by material: assign a palette index per unique material_id.
|
||||
mat_ids = []
|
||||
for p in self._patches:
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from pydantic import ValidationError
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtWidgets import (
|
||||
QDialog,
|
||||
|
|
@ -17,7 +18,6 @@ from PySide6.QtWidgets import (
|
|||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
from pydantic import ValidationError
|
||||
|
||||
from otko.commands import (
|
||||
AddSectionsCommand,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ from PySide6.QtWidgets import (
|
|||
|
||||
from otko.core import Project, UniformExcitationPattern
|
||||
|
||||
|
||||
_DIRECTION_CHOICES: list[tuple[int, str]] = [
|
||||
(1, "1 — X (horizontal)"),
|
||||
(2, "2 — Y (vertical for ndm=2, lateral for ndm=3)"),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, Callable
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from PySide6.QtCore import Qt, Signal
|
||||
from PySide6.QtWidgets import (
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ Exposes two signals:
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
|
||||
from PySide6.QtCore import Qt, Signal
|
||||
from PySide6.QtWidgets import (
|
||||
QComboBox,
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ For 2D it's [N1, Vy1, Mz1, N2, Vy2, Mz2].
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
from typing import Any
|
||||
|
||||
import pyqtgraph as pg
|
||||
|
|
@ -337,8 +338,6 @@ class HysteresisView(QWidget):
|
|||
|
||||
def _clear_curve(self) -> None:
|
||||
if self._curve is not None:
|
||||
try:
|
||||
with contextlib.suppress(Exception):
|
||||
self._plot.removeItem(self._curve)
|
||||
except Exception:
|
||||
pass
|
||||
self._curve = None
|
||||
|
|
|
|||
|
|
@ -8,9 +8,8 @@ dumb: no direct Project mutation, no Qt ↔ OpenSees coupling.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Callable
|
||||
from collections.abc import Callable
|
||||
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtWidgets import (
|
||||
QComboBox,
|
||||
QDoubleSpinBox,
|
||||
|
|
@ -26,7 +25,6 @@ from PySide6.QtWidgets import (
|
|||
|
||||
from otko.core import Project
|
||||
|
||||
|
||||
# Element types the Properties dock lets the user switch between.
|
||||
# "ElasticBeamColumn" needs a section; "Truss" / "CorotTruss" need a
|
||||
# uniaxial material + area. The Convert command drops/adds fields to
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ from PySide6.QtWidgets import (
|
|||
QWidget,
|
||||
)
|
||||
|
||||
from otko.core import UnitLabels, UnitSystem, labels_for
|
||||
from otko.core import UnitSystem, labels_for
|
||||
from otko.services.results import PushoverResults
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Two panels:
|
|||
from __future__ import annotations
|
||||
|
||||
import pyqtgraph as pg
|
||||
from PySide6.QtCore import Signal
|
||||
from PySide6.QtCore import Qt, Signal
|
||||
from PySide6.QtWidgets import (
|
||||
QHBoxLayout,
|
||||
QHeaderView,
|
||||
|
|
@ -20,7 +20,6 @@ from PySide6.QtWidgets import (
|
|||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
from PySide6.QtCore import Qt
|
||||
|
||||
from otko.core import ResponseSpectrum
|
||||
from otko.services.results import ResponseSpectrumResults
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ def _fmt(value: Any) -> str:
|
|||
return "—"
|
||||
if isinstance(value, float):
|
||||
return f"{value:g}"
|
||||
if isinstance(value, (list, tuple)):
|
||||
if isinstance(value, list | tuple):
|
||||
return ", ".join(_fmt(v) for v in value)
|
||||
return str(value)
|
||||
|
||||
|
|
@ -1035,7 +1035,7 @@ class TableDock(QWidget):
|
|||
try:
|
||||
key = int(pid)
|
||||
label = name_of.get(key, str(key)) or str(key)
|
||||
parts.append(f"{label}×{float(factor):g}") # noqa: RUF001
|
||||
parts.append(f"{label}×{float(factor):g}")
|
||||
except (TypeError, ValueError):
|
||||
continue
|
||||
return ", ".join(parts) if parts else "—"
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@ runner to record additional series (planned for a later phase).
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
from typing import Any
|
||||
|
||||
import numpy as np
|
||||
import pyqtgraph as pg
|
||||
from PySide6.QtCore import Signal
|
||||
from PySide6.QtWidgets import (
|
||||
|
|
@ -208,9 +208,7 @@ class TimeHistoryView(QWidget):
|
|||
|
||||
def _clear_traces(self) -> None:
|
||||
for _, _, item in self._traces:
|
||||
try:
|
||||
with contextlib.suppress(Exception):
|
||||
self._plot.removeItem(item)
|
||||
except Exception:
|
||||
pass
|
||||
self._traces.clear()
|
||||
self._trace_list.clear()
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ class MainWindow(
|
|||
if state is not None:
|
||||
self.restoreState(state)
|
||||
|
||||
def closeEvent(self, event: QCloseEvent) -> None: # noqa: N802 (Qt override)
|
||||
def closeEvent(self, event: QCloseEvent) -> None: # (Qt override)
|
||||
"""Prompt to save unsaved work, then persist the window layout.
|
||||
|
||||
The prompt is shown only for a visible window: Qt also closes hidden
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ class CanvasTool(QObject):
|
|||
|
||||
def __init__(
|
||||
self,
|
||||
canvas: "ModelCanvas",
|
||||
vm: "ProjectViewModel",
|
||||
canvas: ModelCanvas,
|
||||
vm: ProjectViewModel,
|
||||
parent: QObject | None = None,
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
|
|
@ -87,7 +87,7 @@ class ToolController(QObject):
|
|||
toolChanged = Signal(object) # emits the new CanvasTool (or None for default)
|
||||
|
||||
def __init__(
|
||||
self, canvas: "ModelCanvas", vm: "ProjectViewModel", parent: QObject | None = None
|
||||
self, canvas: ModelCanvas, vm: ProjectViewModel, parent: QObject | None = None
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
self._canvas = canvas
|
||||
|
|
|
|||
|
|
@ -41,9 +41,9 @@ class DrawFrameTool(LinearElementDrawTool):
|
|||
|
||||
def __init__(
|
||||
self,
|
||||
canvas: "ModelCanvas",
|
||||
vm: "ProjectViewModel",
|
||||
parent: "QObject | None" = None,
|
||||
canvas: ModelCanvas,
|
||||
vm: ProjectViewModel,
|
||||
parent: QObject | None = None,
|
||||
) -> None:
|
||||
super().__init__(canvas, vm, parent)
|
||||
|
||||
|
|
|
|||
|
|
@ -115,9 +115,9 @@ class DrawNodeTool(CanvasTool):
|
|||
|
||||
def __init__(
|
||||
self,
|
||||
canvas: "ModelCanvas",
|
||||
vm: "ProjectViewModel",
|
||||
parent: "QObject | None" = None,
|
||||
canvas: ModelCanvas,
|
||||
vm: ProjectViewModel,
|
||||
parent: QObject | None = None,
|
||||
) -> None:
|
||||
super().__init__(canvas, vm, parent)
|
||||
|
||||
|
|
|
|||
|
|
@ -37,9 +37,9 @@ class DrawTrussTool(LinearElementDrawTool):
|
|||
|
||||
def __init__(
|
||||
self,
|
||||
canvas: "ModelCanvas",
|
||||
vm: "ProjectViewModel",
|
||||
parent: "QObject | None" = None,
|
||||
canvas: ModelCanvas,
|
||||
vm: ProjectViewModel,
|
||||
parent: QObject | None = None,
|
||||
) -> None:
|
||||
super().__init__(canvas, vm, parent)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.commands import ( # noqa: E402
|
||||
from otko.commands import (
|
||||
AddAnalysisCasesCommand,
|
||||
DeleteAnalysisCasesCommand,
|
||||
UpdateAnalysisCaseCommand,
|
||||
)
|
||||
from otko.core import ( # noqa: E402
|
||||
from otko.core import (
|
||||
LinearTimeSeries,
|
||||
ModalCase,
|
||||
NodalLoad,
|
||||
|
|
@ -20,7 +20,7 @@ from otko.core import ( # noqa: E402
|
|||
StaticCase,
|
||||
TransientCase,
|
||||
)
|
||||
from otko.viewmodels import ProjectViewModel # noqa: E402
|
||||
from otko.viewmodels import ProjectViewModel
|
||||
|
||||
|
||||
def _vm_with_pattern() -> ProjectViewModel:
|
||||
|
|
|
|||
|
|
@ -12,21 +12,21 @@ import pytest
|
|||
pytest.importorskip("PySide6")
|
||||
pytest.importorskip("openseespy.opensees")
|
||||
|
||||
from otko.commands import ( # noqa: E402
|
||||
from otko.commands import (
|
||||
AddAnalysisCasesCommand,
|
||||
AddElementsCommand,
|
||||
AddNodalLoadsCommand,
|
||||
AddNodesCommand,
|
||||
AddSectionsCommand,
|
||||
)
|
||||
from otko.core import ( # noqa: E402
|
||||
from otko.core import (
|
||||
ElasticBeamColumn,
|
||||
ElasticSection,
|
||||
Node,
|
||||
StaticCase,
|
||||
)
|
||||
from otko.services.results import StaticResults # noqa: E402
|
||||
from otko.viewmodels import AnalysisRunner, ProjectViewModel # noqa: E402
|
||||
from otko.services.results import StaticResults
|
||||
from otko.viewmodels import AnalysisRunner, ProjectViewModel
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
|
|||
|
|
@ -6,15 +6,14 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.commands import AddNodalLoadsCommand # noqa: E402
|
||||
from otko.core import ( # noqa: E402
|
||||
from otko.commands import AddNodalLoadsCommand
|
||||
from otko.core import (
|
||||
LinearTimeSeries,
|
||||
Node,
|
||||
PlainLoadPattern,
|
||||
Project,
|
||||
)
|
||||
from otko.viewmodels import ProjectViewModel # noqa: E402
|
||||
from otko.views.dialogs.assign_load import AssignLoadDialog # noqa: E402
|
||||
from otko.viewmodels import ProjectViewModel
|
||||
from otko.views.dialogs.assign_load import AssignLoadDialog
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.views.dialogs.assign_masses import AssignMassesDialog # noqa: E402
|
||||
from otko.views.dialogs.assign_masses import AssignMassesDialog
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.core import ( # noqa: E402
|
||||
from otko.core import (
|
||||
ElasticSection,
|
||||
Node,
|
||||
Project,
|
||||
)
|
||||
from otko.views.dialogs.assign_zls import ( # noqa: E402
|
||||
from otko.views.dialogs.assign_zls import (
|
||||
AssignZeroLengthSectionDialog,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.core import ( # noqa: E402
|
||||
from otko.core import (
|
||||
CoordinateGridSystem,
|
||||
CoordinateSystem,
|
||||
GridSystem,
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.core import ( # noqa: E402
|
||||
from otko.core import (
|
||||
NodalLoad,
|
||||
PlainLoadPattern,
|
||||
StaticCase,
|
||||
TransientCase,
|
||||
)
|
||||
from otko.views.dialogs.case_forms import TransientCaseForm # noqa: E402
|
||||
from otko.views.dialogs.case_forms import TransientCaseForm
|
||||
|
||||
|
||||
def _patterns(): # type: ignore[no-untyped-def]
|
||||
|
|
|
|||
|
|
@ -11,15 +11,14 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.commands import ( # noqa: E402
|
||||
from otko.commands import (
|
||||
AddElementsCommand,
|
||||
AddNodalLoadsCommand,
|
||||
AddNodesCommand,
|
||||
DeleteElementsCommand,
|
||||
DeleteNodesCommand,
|
||||
SetRestraintCommand,
|
||||
)
|
||||
from otko.core import ( # noqa: E402
|
||||
from otko.core import (
|
||||
LinearTimeSeries,
|
||||
NodalLoad,
|
||||
Node,
|
||||
|
|
@ -27,7 +26,7 @@ from otko.core import ( # noqa: E402
|
|||
Steel01,
|
||||
TrussElement,
|
||||
)
|
||||
from otko.viewmodels import ProjectViewModel # noqa: E402
|
||||
from otko.viewmodels import ProjectViewModel
|
||||
|
||||
|
||||
# ─────────────────────────── helpers ────────────────────────────────
|
||||
|
|
|
|||
|
|
@ -6,21 +6,21 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.commands import ( # noqa: E402
|
||||
from otko.commands import (
|
||||
AddElementsCommand,
|
||||
AddMaterialsCommand,
|
||||
AddNodesCommand,
|
||||
AddSectionsCommand,
|
||||
ConvertElementTypeCommand,
|
||||
)
|
||||
from otko.core import ( # noqa: E402
|
||||
from otko.core import (
|
||||
ElasticBeamColumn,
|
||||
ElasticSection,
|
||||
ElasticUniaxial,
|
||||
Node,
|
||||
TrussElement,
|
||||
)
|
||||
from otko.viewmodels import ProjectViewModel # noqa: E402
|
||||
from otko.viewmodels import ProjectViewModel
|
||||
|
||||
|
||||
def _vm_setup() -> ProjectViewModel:
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.core import LinearTimeSeries, Project # noqa: E402
|
||||
from otko.views.dialogs.linear_time_series import LinearTimeSeriesDialog # noqa: E402
|
||||
from otko.views.dialogs.plain_pattern import PlainPatternDialog # noqa: E402
|
||||
from otko.core import LinearTimeSeries, Project
|
||||
from otko.views.dialogs.linear_time_series import LinearTimeSeriesDialog
|
||||
from otko.views.dialogs.plain_pattern import PlainPatternDialog
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.commands import AddNodesCommand # noqa: E402
|
||||
from otko.core import ElasticBeamColumn, ElasticSection, Node # noqa: E402
|
||||
from otko.viewmodels import ProjectViewModel # noqa: E402
|
||||
from otko.views.canvas3d import SelectionState # noqa: E402
|
||||
from otko.views.tools.draw_frame import DrawFrameTool # noqa: E402
|
||||
from otko.commands import AddNodesCommand
|
||||
from otko.core import ElasticBeamColumn, ElasticSection, Node
|
||||
from otko.viewmodels import ProjectViewModel
|
||||
from otko.views.canvas3d import SelectionState
|
||||
from otko.views.tools.draw_frame import DrawFrameTool
|
||||
|
||||
|
||||
class _CanvasStub:
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.core import GridSystem, Node, Project # noqa: E402
|
||||
from otko.viewmodels import ProjectViewModel # noqa: E402
|
||||
from otko.views.canvas3d.selection import SelectionState # noqa: E402
|
||||
from otko.views.tools.draw_node import ( # noqa: E402
|
||||
from otko.core import GridSystem, Node
|
||||
from otko.viewmodels import ProjectViewModel
|
||||
from otko.views.canvas3d.selection import SelectionState
|
||||
from otko.views.tools.draw_node import (
|
||||
DrawNodeTool,
|
||||
_snap_to_grid,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -6,18 +6,17 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.core import ( # noqa: E402
|
||||
from otko.core import (
|
||||
CoordinateGridSystem,
|
||||
CoordinateSystem,
|
||||
ElasticUniaxial,
|
||||
GridSystem,
|
||||
Node,
|
||||
TrussElement,
|
||||
make_grid_lines,
|
||||
)
|
||||
from otko.viewmodels import ProjectViewModel # noqa: E402
|
||||
from otko.views.canvas3d.selection import SelectionState # noqa: E402
|
||||
from otko.views.tools.draw_truss import DrawTrussTool # noqa: E402
|
||||
from otko.viewmodels import ProjectViewModel
|
||||
from otko.views.canvas3d.selection import SelectionState
|
||||
from otko.views.tools.draw_truss import DrawTrussTool
|
||||
|
||||
|
||||
class _CanvasStub:
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.core import ( # noqa: E402
|
||||
from otko.core import (
|
||||
CoordinateGridSystem,
|
||||
CoordinateSystem,
|
||||
GridLine,
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.core import Concrete04 # noqa: E402
|
||||
from otko.views.dialogs.material_forms import ( # noqa: E402
|
||||
Concrete04Form,
|
||||
from otko.core import Concrete04
|
||||
from otko.views.dialogs.material_forms import (
|
||||
FORM_REGISTRY,
|
||||
Concrete04Form,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.views.dialogs.material_forms import ( # noqa: E402
|
||||
from otko.views.dialogs.material_forms import (
|
||||
Concrete01Form,
|
||||
Concrete02Form,
|
||||
Steel01Form,
|
||||
|
|
|
|||
|
|
@ -8,17 +8,16 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.commands import ( # noqa: E402
|
||||
from otko.commands import (
|
||||
AddLoadPatternCommand,
|
||||
AddTimeSeriesCommand,
|
||||
)
|
||||
from otko.core import ( # noqa: E402
|
||||
Node,
|
||||
from otko.core import (
|
||||
PathTimeSeries,
|
||||
Project,
|
||||
UniformExcitationPattern,
|
||||
)
|
||||
from otko.viewmodels import ProjectViewModel # noqa: E402
|
||||
from otko.viewmodels import ProjectViewModel
|
||||
|
||||
|
||||
# ─────────────── AddTimeSeriesCommand / AddLoadPatternCommand ──────────────
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.commands import ( # noqa: E402
|
||||
from otko.commands import (
|
||||
AddElementsCommand,
|
||||
AddMaterialsCommand,
|
||||
AddNodesCommand,
|
||||
|
|
@ -16,7 +16,7 @@ from otko.commands import ( # noqa: E402
|
|||
UpdateMaterialCommand,
|
||||
UpdateSectionCommand,
|
||||
)
|
||||
from otko.core import ( # noqa: E402
|
||||
from otko.core import (
|
||||
ElasticBeamColumn,
|
||||
ElasticSection,
|
||||
Node,
|
||||
|
|
@ -24,7 +24,7 @@ from otko.core import ( # noqa: E402
|
|||
Steel02,
|
||||
TrussElement,
|
||||
)
|
||||
from otko.viewmodels import ProjectViewModel # noqa: E402
|
||||
from otko.viewmodels import ProjectViewModel
|
||||
|
||||
|
||||
def _vm_with_steel() -> ProjectViewModel:
|
||||
|
|
|
|||
|
|
@ -10,13 +10,10 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.core import ( # noqa: E402
|
||||
Concrete01,
|
||||
from otko.core import (
|
||||
Concrete02,
|
||||
ElasticIsotropic,
|
||||
ElasticPP,
|
||||
ElasticSection,
|
||||
ElasticUniaxial,
|
||||
Steel01,
|
||||
Steel02,
|
||||
)
|
||||
|
|
@ -100,10 +97,14 @@ def test_elastic_section_form_round_trip(qtbot) -> None: # type: ignore[no-unty
|
|||
def test_form_for_dispatches_by_type(qtbot) -> None: # type: ignore[no-untyped-def]
|
||||
from otko.views.dialogs.material_forms import (
|
||||
Steel01Form,
|
||||
)
|
||||
from otko.views.dialogs.material_forms import (
|
||||
form_for as material_form_for,
|
||||
)
|
||||
from otko.views.dialogs.section_forms import (
|
||||
ElasticSectionForm,
|
||||
)
|
||||
from otko.views.dialogs.section_forms import (
|
||||
form_for as section_form_for,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.core import UnitSystem # noqa: E402
|
||||
from otko.services.results import PushoverResults # noqa: E402
|
||||
from otko.views.docks.pushover_curve import ( # noqa: E402
|
||||
from otko.core import UnitSystem
|
||||
from otko.services.results import PushoverResults
|
||||
from otko.views.docks.pushover_curve import (
|
||||
PushoverCurveView,
|
||||
_is_rotation_dof,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from PySide6.QtCore import QObject, Signal # noqa: E402
|
||||
from PySide6.QtCore import QObject, Signal
|
||||
|
||||
from otko.core import LinearTimeSeries, PlainLoadPattern, Project, TransientCase # noqa: E402
|
||||
from otko.viewmodels import ProjectViewModel # noqa: E402
|
||||
from otko.views.dialogs.run_analysis import RunAnalysisDialog # noqa: E402
|
||||
from otko.core import LinearTimeSeries, PlainLoadPattern, TransientCase
|
||||
from otko.viewmodels import ProjectViewModel
|
||||
from otko.views.dialogs.run_analysis import RunAnalysisDialog
|
||||
|
||||
|
||||
class _FakeRunner(QObject):
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.core import ( # noqa: E402
|
||||
from otko.core import (
|
||||
ElasticBeamColumn,
|
||||
ElasticSection,
|
||||
Node,
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.core import ( # noqa: E402
|
||||
from otko.core import (
|
||||
AggregatorDOF,
|
||||
ElasticSection,
|
||||
FiberSection,
|
||||
RectangularPatch,
|
||||
SectionAggregator,
|
||||
)
|
||||
from otko.views.dialogs.section_forms import ( # noqa: E402
|
||||
from otko.views.dialogs.section_forms import (
|
||||
FORM_REGISTRY,
|
||||
form_for,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.views.canvas3d import SelectionState # noqa: E402
|
||||
from otko.views.canvas3d import SelectionState
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
|
|
|
|||
|
|
@ -6,15 +6,15 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.commands import ( # noqa: E402
|
||||
from otko.commands import (
|
||||
AddElementsCommand,
|
||||
AddNodesCommand,
|
||||
MirrorCommand,
|
||||
MoveNodesCommand,
|
||||
ReplicateCommand,
|
||||
)
|
||||
from otko.core import Node, Steel01, TrussElement # noqa: E402
|
||||
from otko.viewmodels import ProjectViewModel # noqa: E402
|
||||
from otko.core import Node, Steel01, TrussElement
|
||||
from otko.viewmodels import ProjectViewModel
|
||||
|
||||
|
||||
def _populated_vm() -> ProjectViewModel:
|
||||
|
|
|
|||
|
|
@ -6,10 +6,9 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from PySide6.QtCore import Qt # noqa: E402
|
||||
from PySide6.QtWidgets import QTreeWidget # noqa: E402
|
||||
from PySide6.QtWidgets import QTreeWidget
|
||||
|
||||
from otko.core import Node # noqa: E402
|
||||
from otko.core import Node
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.core import UnitSystem # noqa: E402
|
||||
from otko.core import UnitSystem
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
|
|
|
|||
|
|
@ -6,18 +6,18 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.commands import ( # noqa: E402
|
||||
from otko.commands import (
|
||||
AddElementsCommand,
|
||||
AddMaterialsCommand,
|
||||
AddNodesCommand,
|
||||
UpdateElementFieldsCommand,
|
||||
)
|
||||
from otko.core import ( # noqa: E402
|
||||
from otko.core import (
|
||||
ElasticUniaxial,
|
||||
Node,
|
||||
TrussElement,
|
||||
)
|
||||
from otko.viewmodels import ProjectViewModel # noqa: E402
|
||||
from otko.viewmodels import ProjectViewModel
|
||||
|
||||
|
||||
def _vm_with_truss() -> ProjectViewModel:
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import pytest
|
|||
|
||||
pytest.importorskip("PySide6")
|
||||
|
||||
from otko.core import ( # noqa: E402
|
||||
from otko.core import (
|
||||
CoordinateGridSystem,
|
||||
GridSystem,
|
||||
Project,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import pytest
|
|||
|
||||
pytest.importorskip("openseespy")
|
||||
|
||||
from otko.services.opensees_runner import OpenSeesRunner # noqa: E402
|
||||
from otko.services.opensees_runner import OpenSeesRunner
|
||||
|
||||
pytestmark = pytest.mark.slow
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ def test_basic_truss_matches_opensees_tcl_reference() -> None:
|
|||
a linear rescale of the Tcl model — any deviation would flag a
|
||||
real solver/translation issue.
|
||||
"""
|
||||
from examples.basic_truss import build_basic_truss, IN_TO_M
|
||||
from examples.basic_truss import IN_TO_M, build_basic_truss
|
||||
|
||||
proj = build_basic_truss()
|
||||
runner = OpenSeesRunner(proj)
|
||||
|
|
@ -45,6 +45,7 @@ def test_basic_truss_matches_opensees_tcl_reference() -> None:
|
|||
def test_basic_truss_round_trips(tmp_path) -> None: # type: ignore[no-untyped-def]
|
||||
"""The example project must survive save/load without any information loss."""
|
||||
from examples.basic_truss import build_basic_truss
|
||||
|
||||
from otko.services import load_project, save_project
|
||||
|
||||
p = build_basic_truss()
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ import pytest
|
|||
|
||||
pytest.importorskip("openseespy")
|
||||
|
||||
from otko.services import load_project, save_project # noqa: E402
|
||||
from otko.services.opensees_runner import OpenSeesRunner # noqa: E402
|
||||
from otko.services import load_project, save_project
|
||||
from otko.services.opensees_runner import OpenSeesRunner
|
||||
|
||||
pytestmark = pytest.mark.slow
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import pytest
|
|||
|
||||
ops = pytest.importorskip("openseespy.opensees") # skip if OpenSeesPy not installed
|
||||
|
||||
from otko.core import ( # noqa: E402
|
||||
from otko.core import (
|
||||
ElasticBeamColumn,
|
||||
ElasticSection,
|
||||
LinearTimeSeries,
|
||||
|
|
@ -20,8 +20,8 @@ from otko.core import ( # noqa: E402
|
|||
Project,
|
||||
StaticCase,
|
||||
)
|
||||
from otko.services import OpenSeesRunner, evaluate_combination # noqa: E402
|
||||
from otko.services.results import StaticResults # noqa: E402
|
||||
from otko.services import OpenSeesRunner, evaluate_combination
|
||||
from otko.services.results import StaticResults
|
||||
|
||||
pytestmark = pytest.mark.slow
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import pytest
|
|||
|
||||
pytest.importorskip("openseespy")
|
||||
|
||||
from otko.core import ( # noqa: E402
|
||||
from otko.core import (
|
||||
Concrete04,
|
||||
FiberSection,
|
||||
ForceBeamColumn,
|
||||
|
|
@ -32,7 +32,7 @@ from otko.core import ( # noqa: E402
|
|||
StaticCase,
|
||||
UnitSystem,
|
||||
)
|
||||
from otko.services.opensees_runner import OpenSeesRunner # noqa: E402
|
||||
from otko.services.opensees_runner import OpenSeesRunner
|
||||
|
||||
pytestmark = pytest.mark.slow
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import pytest
|
|||
|
||||
pytest.importorskip("openseespy")
|
||||
|
||||
from otko.core import ( # noqa: E402
|
||||
from otko.core import (
|
||||
ElasticUniaxial,
|
||||
LinearTimeSeries,
|
||||
NodalLoad,
|
||||
|
|
@ -21,7 +21,7 @@ from otko.core import ( # noqa: E402
|
|||
StaticCase,
|
||||
TrussElement,
|
||||
)
|
||||
from otko.services.opensees_runner import OpenSeesRunner # noqa: E402
|
||||
from otko.services.opensees_runner import OpenSeesRunner
|
||||
|
||||
pytestmark = pytest.mark.slow
|
||||
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ import pytest
|
|||
|
||||
pytest.importorskip("openseespy")
|
||||
|
||||
from otko.core import ModalCase # noqa: E402
|
||||
from otko.services import load_project, save_project # noqa: E402
|
||||
from otko.services.opensees_runner import OpenSeesRunner # noqa: E402
|
||||
from otko.core import ModalCase
|
||||
from otko.services import load_project, save_project
|
||||
from otko.services.opensees_runner import OpenSeesRunner
|
||||
|
||||
pytestmark = pytest.mark.slow
|
||||
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ import pytest
|
|||
|
||||
pytest.importorskip("openseespy")
|
||||
|
||||
from otko.core import ModalCase # noqa: E402
|
||||
from otko.services import load_project, save_project # noqa: E402
|
||||
from otko.services.opensees_runner import OpenSeesRunner # noqa: E402
|
||||
from otko.core import ModalCase
|
||||
from otko.services import load_project, save_project
|
||||
from otko.services.opensees_runner import OpenSeesRunner
|
||||
|
||||
pytestmark = pytest.mark.slow
|
||||
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ import pytest
|
|||
|
||||
pytest.importorskip("openseespy")
|
||||
|
||||
from otko.core import ModalCase, StaticCase # noqa: E402
|
||||
from otko.services import load_project, save_project # noqa: E402
|
||||
from otko.services.opensees_runner import OpenSeesRunner # noqa: E402
|
||||
from otko.core import ModalCase, StaticCase
|
||||
from otko.services import load_project, save_project
|
||||
from otko.services.opensees_runner import OpenSeesRunner
|
||||
|
||||
pytestmark = pytest.mark.slow
|
||||
|
||||
|
|
@ -29,7 +29,6 @@ def _reload(proj, tmp_path): # type: ignore[no-untyped-def]
|
|||
def test_elastic_frame_gravity_reactions(tmp_path) -> None: # type: ignore[no-untyped-def]
|
||||
"""ΣFy at base = total applied gravity (distributed w × beam × floors)."""
|
||||
from examples.elastic_frame import (
|
||||
BAY,
|
||||
LOAD_F1,
|
||||
LOAD_F2,
|
||||
LOAD_F3,
|
||||
|
|
@ -70,7 +69,6 @@ def test_elastic_frame_gravity_reactions(tmp_path) -> None: # type: ignore[no-u
|
|||
def test_elastic_frame_gravity_plus_lateral_reactions(tmp_path) -> None: # type: ignore[no-untyped-def]
|
||||
"""ΣFx at base must equal -(lateral applied) within PDelta tolerance."""
|
||||
from examples.elastic_frame import (
|
||||
BAY,
|
||||
LOAD_F1,
|
||||
LOAD_F2,
|
||||
LOAD_F3,
|
||||
|
|
@ -120,5 +118,5 @@ def test_elastic_frame_modal_periods(tmp_path) -> None: # type: ignore[no-untyp
|
|||
# 0.1930, 0.1562, 0.130 s. Our solve nails these within 1.5%.
|
||||
expected = [1.040, 0.3526, 0.1930, 0.1562, 0.130]
|
||||
periods = [2.0 * math.pi / math.sqrt(v) for v in r.eigenvalues]
|
||||
for i, (T, T_ref) in enumerate(zip(periods, expected), start=1):
|
||||
assert T == pytest.approx(T_ref, rel=0.02), f"T{i} = {T:.4f} s, reference {T_ref:.4f} s"
|
||||
for i, (T, T_ref) in enumerate(zip(periods, expected, strict=False), start=1):
|
||||
assert pytest.approx(T_ref, rel=0.02) == T, f"T{i} = {T:.4f} s, reference {T_ref:.4f} s"
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ import pytest
|
|||
|
||||
pytest.importorskip("openseespy")
|
||||
|
||||
from otko.core import PushoverCase, TransientCase # noqa: E402
|
||||
from otko.services import load_project, save_project # noqa: E402
|
||||
from otko.services.opensees_runner import OpenSeesRunner # noqa: E402
|
||||
from otko.core import PushoverCase, TransientCase
|
||||
from otko.services import load_project, save_project
|
||||
from otko.services.opensees_runner import OpenSeesRunner
|
||||
|
||||
pytestmark = pytest.mark.slow
|
||||
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ import pytest
|
|||
|
||||
pytest.importorskip("openseespy")
|
||||
|
||||
from otko.services import load_project, save_project # noqa: E402
|
||||
from otko.services.opensees_runner import OpenSeesRunner # noqa: E402
|
||||
from otko.services import load_project, save_project
|
||||
from otko.services.opensees_runner import OpenSeesRunner
|
||||
|
||||
pytestmark = pytest.mark.slow
|
||||
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ import pytest
|
|||
|
||||
pytest.importorskip("openseespy")
|
||||
|
||||
from otko.core import PushoverCase, TransientCase # noqa: E402
|
||||
from otko.services import load_project, save_project # noqa: E402
|
||||
from otko.services.opensees_runner import OpenSeesRunner # noqa: E402
|
||||
from otko.core import PushoverCase, TransientCase
|
||||
from otko.services import load_project, save_project
|
||||
from otko.services.opensees_runner import OpenSeesRunner
|
||||
|
||||
pytestmark = pytest.mark.slow
|
||||
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ import pytest
|
|||
|
||||
pytest.importorskip("openseespy")
|
||||
|
||||
from otko.core import PushoverCase, TransientCase # noqa: E402
|
||||
from otko.services import load_project, save_project # noqa: E402
|
||||
from otko.services.opensees_runner import OpenSeesRunner # noqa: E402
|
||||
from otko.core import PushoverCase, TransientCase
|
||||
from otko.services import load_project, save_project
|
||||
from otko.services.opensees_runner import OpenSeesRunner
|
||||
|
||||
pytestmark = pytest.mark.slow
|
||||
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ import pytest
|
|||
|
||||
pytest.importorskip("openseespy")
|
||||
|
||||
from otko.core import PushoverCase, TransientCase # noqa: E402
|
||||
from otko.services import load_project, save_project # noqa: E402
|
||||
from otko.services.opensees_runner import OpenSeesRunner # noqa: E402
|
||||
from otko.core import PushoverCase, TransientCase
|
||||
from otko.services import load_project, save_project
|
||||
from otko.services.opensees_runner import OpenSeesRunner
|
||||
|
||||
pytestmark = pytest.mark.slow
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue