Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[flake8]
exclude = venv, .tox
ignore = E203, E266, E501, W503, C901, E741
max-line-length = 88
max-complexity = 18
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@ jobs:
- name: Test with tox
run: |
pip install tox
tox -- --cov meshio --cov-report xml --cov-report term
tox -e py${{ matrix.python-version == '3.8' && '38' || '312' }} -- --cov meshio --cov-report xml --cov-report term
- uses: codecov/codecov-action@v3
if: ${{ matrix.python-version == '3.10' && matrix.os == 'ubuntu-latest' }}
13 changes: 8 additions & 5 deletions src/meshio/__about__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
try:
# Python 3.8+
from importlib import metadata
except ImportError:
try:
import importlib_metadata as metadata
except ImportError:
__version__ = "unknown"
metadata = None

try:
__version__ = metadata.version("meshio")
except Exception:

if metadata is not None:
try:
__version__ = metadata.version("meshio")
except Exception:
__version__ = "unknown"
else:
__version__ = "unknown"
2 changes: 1 addition & 1 deletion src/meshio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
write,
write_points_cells,
)
from ._mesh import CellBlock, Mesh
from ._mesh import CellBlock, Mesh, topological_dimension

__all__ = [
"abaqus",
Expand Down
5 changes: 2 additions & 3 deletions src/meshio/_cli/_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@ def main(argv=None):
help="display version information",
)

subparsers = parent_parser.add_subparsers(
title="subcommands", dest="command", required=True
)
subparsers = parent_parser.add_subparsers(title="subcommands", dest="command")
subparsers.required = True

parser = subparsers.add_parser("convert", help="Convert mesh files", aliases=["c"])
_convert.add_args(parser)
Expand Down
27 changes: 13 additions & 14 deletions src/meshio/_helpers.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from __future__ import annotations

import sys
from pathlib import Path
from typing import Union

import numpy as np
from numpy.typing import ArrayLike

from ._common import error, num_nodes_per_cell
from ._common import num_nodes_per_cell
from ._exceptions import ReadError, WriteError
from ._files import is_buffer
from ._mesh import CellBlock, Mesh
Expand Down Expand Up @@ -57,7 +57,7 @@ def _filetypes_from_path(path: Path) -> list[str]:
return out


def read(filename, file_format: str | None = None):
def read(filename, file_format: Union[str, None] = None):
"""Reads an unstructured mesh with added data.

:param filenames: The files/PathLikes to read from.
Expand All @@ -71,7 +71,7 @@ def read(filename, file_format: str | None = None):
return _read_file(Path(filename), file_format)


def _read_buffer(filename, file_format: str | None):
def _read_buffer(filename, file_format: Union[str, None]):
if file_format is None:
raise ReadError("File format must be given if buffer is used")
if file_format == "tetgen":
Expand All @@ -85,7 +85,7 @@ def _read_buffer(filename, file_format: str | None):
return reader_map[file_format](filename)


def _read_file(path: Path, file_format: str | None):
def _read_file(path: Path, file_format: Union[str, None]):
if not path.exists():
raise ReadError(f"File {path} not found.")

Expand All @@ -110,20 +110,19 @@ def _read_file(path: Path, file_format: str | None):
lst = ", ".join(possible_file_formats)
msg = f"Couldn't read file {path} as either of {lst}"

error(msg)
sys.exit(1)
raise ReadError(msg)


def write_points_cells(
filename,
points: ArrayLike,
cells: dict[str, ArrayLike] | list[tuple[str, ArrayLike] | CellBlock],
point_data: dict[str, ArrayLike] | None = None,
cell_data: dict[str, list[ArrayLike]] | None = None,
cells: Union[dict[str, ArrayLike], list[Union[tuple[str, ArrayLike], CellBlock]]],
point_data: Union[dict[str, ArrayLike], None] = None,
cell_data: Union[dict[str, list[ArrayLike]], None] = None,
field_data=None,
point_sets: dict[str, ArrayLike] | None = None,
cell_sets: dict[str, list[ArrayLike]] | None = None,
file_format: str | None = None,
point_sets: Union[dict[str, ArrayLike], None] = None,
cell_sets: Union[dict[str, list[ArrayLike]], None] = None,
file_format: Union[str, None] = None,
**kwargs,
):
points = np.asarray(points)
Expand All @@ -139,7 +138,7 @@ def write_points_cells(
mesh.write(filename, file_format=file_format, **kwargs)


def write(filename, mesh: Mesh, file_format: str | None = None, **kwargs):
def write(filename, mesh: Mesh, file_format: Union[str, None] = None, **kwargs):
"""Writes mesh together with data to a file.

:params filename: File to write to.
Expand Down
21 changes: 12 additions & 9 deletions src/meshio/_mesh.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import copy
from typing import Union

import numpy as np
from numpy.typing import ArrayLike
Expand Down Expand Up @@ -86,8 +87,8 @@ class CellBlock:
def __init__(
self,
cell_type: str,
data: list | np.ndarray,
tags: list[str] | None = None,
data: Union[list, np.ndarray],
tags: Union[list[str], None] = None,
):
self.type = cell_type
self.data = data
Expand Down Expand Up @@ -117,12 +118,14 @@ class Mesh:
def __init__(
self,
points: ArrayLike,
cells: dict[str, ArrayLike] | list[tuple[str, ArrayLike] | CellBlock],
point_data: dict[str, ArrayLike] | None = None,
cell_data: dict[str, list[ArrayLike]] | None = None,
cells: Union[
dict[str, ArrayLike], list[Union[tuple[str, ArrayLike], CellBlock]]
],
point_data: Union[dict[str, ArrayLike], None] = None,
cell_data: Union[dict[str, list[ArrayLike]], None] = None,
field_data=None,
point_sets: dict[str, ArrayLike] | None = None,
cell_sets: dict[str, list[ArrayLike]] | None = None,
point_sets: Union[dict[str, ArrayLike], None] = None,
cell_sets: Union[dict[str, list[ArrayLike]], None] = None,
gmsh_periodic=None,
info=None,
):
Expand Down Expand Up @@ -234,7 +237,7 @@ def __repr__(self):
def copy(self):
return copy.deepcopy(self)

def write(self, path_or_buf, file_format: str | None = None, **kwargs):
def write(self, path_or_buf, file_format: Union[str, None] = None, **kwargs):
# avoid circular import
from ._helpers import write

Expand Down Expand Up @@ -313,7 +316,7 @@ def read(cls, path_or_buf, file_format=None):
warn("meshio.Mesh.read is deprecated, use meshio.read instead")
return read(path_or_buf, file_format)

def cell_sets_to_data(self, data_name: str | None = None):
def cell_sets_to_data(self, data_name: Union[str, None] = None):
# If possible, convert cell sets to integer cell data. This is possible if all
# cells appear exactly in one group.
default_value = -1
Expand Down
2 changes: 1 addition & 1 deletion src/meshio/dolfin/_dolfin.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ def _write_cell_data(filename, dim, cell_data):
)

for k, value in enumerate(cell_data):
ET.SubElement(mesh_function, "entity", index=str(k), value=repr(value))
ET.SubElement(mesh_function, "entity", index=str(k), value=str(value))

tree = ET.ElementTree(dolfin)
tree.write(filename)
Expand Down
16 changes: 12 additions & 4 deletions src/meshio/gmsh/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,17 @@ def _read_data(f, tag, data_dict, data_size, is_ascii):
num_components = integer_tags[1]
num_items = integer_tags[2]
if is_ascii:
data = np.fromfile(f, count=num_items * (1 + num_components), sep=" ").reshape(
(num_items, 1 + num_components)
)
# We need to read num_items * (1 + num_components) floats.
# np.fromfile(..., sep=" ") can be flaky if there are newlines or other
# whitespace issues.
# Instead, read the raw string and split it.
data = []
while len(data) < num_items * (1 + num_components):
line = f.readline().decode().split()
if not line:
break
data.extend([float(val) for val in line])
data = np.array(data).reshape((num_items, 1 + num_components))
# The first entry is the node number
data = data[:, 1:]
else:
Expand Down Expand Up @@ -273,7 +281,7 @@ def _write_data(fh, tag, name, data, binary):
tmp.tofile(fh)
fh.write(b"\n")
else:
fmt = " ".join(["{}"] + ["{!r}"] * num_components) + "\n"
fmt = " ".join(["{}"] + ["{!s}"] * num_components) + "\n"
# TODO unify
if num_components == 1:
for k, x in enumerate(data):
Expand Down
2 changes: 1 addition & 1 deletion src/meshio/mdpa/_mdpa.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ def _write_data(fh, tag, name, data, binary):
data = data[:, 0]

# Actually write the data
fmt = " ".join(["{}"] + ["{!r}"] * num_components) + "\n"
fmt = " ".join(["{}"] + ["{!s}"] * num_components) + "\n"
# TODO unify
if num_components == 1:
for k, x in enumerate(data):
Expand Down
2 changes: 1 addition & 1 deletion src/meshio/med/_med.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ def _create_component_names(n_components):
"""To be correctly read in a MED viewer, each component must be a string of width
16. Since we do not know the physical nature of the data, we just use V1, V2,...
"""
return [f"V{(i+1)}" for i in range(n_components)]
return [f"V{(i + 1)}" for i in range(n_components)]


def _family_name(set_id, name):
Expand Down
5 changes: 3 additions & 2 deletions src/meshio/stl/_stl.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from __future__ import annotations

import os
from typing import Union

import numpy as np

Expand Down Expand Up @@ -51,9 +52,9 @@ def read(filename):
def iter_loadtxt(
infile,
skiprows: int = 0,
comments: str | tuple[str, ...] = "#",
comments: Union[str, tuple[str, ...]] = "#",
dtype=float,
usecols: tuple[int] | None = None,
usecols: Union[tuple[int], None] = None,
):
def iter_func():
items = None
Expand Down
5 changes: 3 additions & 2 deletions src/meshio/svg/_svg.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

from typing import Union
from xml.etree import ElementTree as ET

import numpy as np
Expand All @@ -12,11 +13,11 @@ def write(
filename,
mesh,
float_fmt: str = ".3f",
stroke_width: str | None = None,
stroke_width: Union[str, None] = None,
# Use a default image_width (not None). If set to None, images will come out at the
# width of the mesh (which is okay). Some viewers (e.g., eog) have problems
# displaying SVGs of width around 1 since they interpret it as the width in pixels.
image_width: int | float | None = 100,
image_width: Union[int, float, None] = 100,
# ParaView's default colors
fill: str = "#c8c5bd",
stroke: str = "#000080",
Expand Down
13 changes: 11 additions & 2 deletions src/meshio/ugrid/_ugrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,16 @@ def read(filename):

def _read_section(f, file_type, count, dtype):
if file_type["type"] == "ascii":
return np.fromfile(f, count=count, dtype=dtype, sep=" ")
# np.fromfile(..., sep=" ") can be flaky if there are newlines or other
# whitespace issues.
# Instead, read the raw string and split it.
data = []
while len(data) < count:
line = f.readline().split()
if not line:
break
data.extend(line)
return np.array(data, dtype=dtype)
return np.fromfile(f, count=count, dtype=dtype)


Expand Down Expand Up @@ -145,7 +154,7 @@ def read_buffer(f, file_type):
def _write_section(f, file_type, array, dtype):
if file_type["type"] == "ascii":
ncols = array.shape[1]
fmt = " ".join(["%r"] * ncols)
fmt = " ".join(["%s"] * ncols)
np.savetxt(f, array, fmt=fmt)
else:
array.astype(dtype).tofile(f)
Expand Down
9 changes: 7 additions & 2 deletions src/meshio/xdmf/time_series.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import os
import pathlib
from io import BytesIO
from typing import Union
from xml.etree import ElementTree as ET

import numpy as np
Expand Down Expand Up @@ -274,7 +275,9 @@ def __exit__(self, *_):
def write_points_cells(
self,
points: ArrayLike,
cells: dict[str, ArrayLike] | list[tuple[str, ArrayLike] | CellBlock],
cells: Union[
dict[str, ArrayLike], list[Union[tuple[str, ArrayLike], CellBlock]]
],
) -> None:
# <Grid Name="mesh" GridType="Uniform">
# <Topology NumberOfElements="16757" TopologyType="Triangle" NodesPerElement="3">
Expand Down Expand Up @@ -361,7 +364,9 @@ def points(self, grid, points):

def cells(
self,
cells: dict[str, ArrayLike] | list[tuple[str, ArrayLike] | CellBlock],
cells: Union[
dict[str, ArrayLike], list[Union[tuple[str, ArrayLike], CellBlock]]
],
grid: ET.Element,
) -> None:
if isinstance(cells, dict):
Expand Down
7 changes: 4 additions & 3 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@
# tox -e lint --> check code formatting and lint the code

[tox]
envlist = py3
envlist = py38, py312
isolated_build = True

[testenv]
deps =
pytest
pytest-codeblocks >= 0.12.1
pytest-cov
# pytest-randomly
extras = all
h5py
netCDF4; sys_platform != "win32" or python_version != "3.8"
# extras = all
commands =
pytest {posargs} --codeblocks

Expand Down
Loading