1
1
from __future__ import annotations
2
2
3
- import pathlib
3
+ import sys
4
+ from pathlib import Path
4
5
5
6
import numpy as np
6
7
from numpy .typing import ArrayLike
7
8
8
- from ._common import num_nodes_per_cell
9
+ from ._common import error , num_nodes_per_cell
9
10
from ._exceptions import ReadError , WriteError
10
11
from ._files import is_buffer
11
12
from ._mesh import CellBlock , Mesh
12
13
13
- extension_to_filetype = {}
14
+ extension_to_filetypes = {}
14
15
reader_map = {}
15
16
_writer_map = {}
16
17
17
18
18
- def register_format (name : str , extensions : list [str ], reader , writer_map ):
19
+ def register_format (
20
+ format_name : str , extensions : list [str ], reader , writer_map
21
+ ) -> None :
19
22
for ext in extensions :
20
- extension_to_filetype [ext ] = name
23
+ if ext not in extension_to_filetypes :
24
+ extension_to_filetypes [ext ] = []
25
+ extension_to_filetypes [ext ].append (format_name )
21
26
22
27
if reader is not None :
23
- reader_map [name ] = reader
28
+ reader_map [format_name ] = reader
29
+
24
30
_writer_map .update (writer_map )
25
31
26
32
27
- def _filetype_from_path (path : pathlib .Path ):
33
+ def deregister_format (format_name : str ):
34
+ for value in extension_to_filetypes .values ():
35
+ if format_name in value :
36
+ value .remove (format_name )
37
+
38
+ if format_name in reader_map :
39
+ reader_map .pop (format_name )
40
+
41
+ if format_name in _writer_map :
42
+ _writer_map .pop (format_name )
43
+
44
+
45
+ def _filetypes_from_path (path : Path ) -> list [str ]:
28
46
ext = ""
29
- out = None
47
+ out = []
30
48
for suffix in reversed (path .suffixes ):
31
49
ext = (suffix + ext ).lower ()
32
- if ext in extension_to_filetype :
33
- out = extension_to_filetype [ext ]
50
+ try :
51
+ out += extension_to_filetypes [ext ]
52
+ except KeyError :
53
+ pass
34
54
35
- if out is None :
36
- raise ReadError (f"Could not deduce file format from extension '{ ext } '." )
55
+ if not out :
56
+ raise ReadError (f"Could not deduce file format from path '{ path } '." )
37
57
return out
38
58
39
59
@@ -46,31 +66,48 @@ def read(filename, file_format: str | None = None):
46
66
:returns mesh{2,3}d: The mesh data.
47
67
"""
48
68
if is_buffer (filename , "r" ):
49
- if file_format is None :
50
- raise ReadError ("File format must be given if buffer is used" )
51
- if file_format == "tetgen" :
52
- raise ReadError (
53
- "tetgen format is spread across multiple files "
54
- "and so cannot be read from a buffer"
55
- )
56
- msg = f"Unknown file format '{ file_format } '"
57
- else :
58
- path = pathlib .Path (filename )
59
- if not path .exists ():
60
- raise ReadError (f"File { filename } not found." )
69
+ return _read_buffer (filename , file_format )
61
70
62
- if not file_format :
63
- # deduce file format from extension
64
- file_format = _filetype_from_path (path )
71
+ return _read_file (Path (filename ), file_format )
65
72
66
- msg = f"Unknown file format '{ file_format } ' of '{ filename } '."
67
73
74
+ def _read_buffer (filename , file_format : str | None ):
75
+ if file_format is None :
76
+ raise ReadError ("File format must be given if buffer is used" )
77
+ if file_format == "tetgen" :
78
+ raise ReadError (
79
+ "tetgen format is spread across multiple files "
80
+ "and so cannot be read from a buffer"
81
+ )
68
82
if file_format not in reader_map :
69
- raise ReadError (msg )
83
+ raise ReadError (f"Unknown file format ' { file_format } '" )
70
84
71
85
return reader_map [file_format ](filename )
72
86
73
87
88
+ def _read_file (path : Path , file_format : str | None ):
89
+ if not path .exists ():
90
+ raise ReadError (f"File { path } not found." )
91
+
92
+ if file_format :
93
+ possible_file_formats = [file_format ]
94
+ else :
95
+ # deduce possible file formats from extension
96
+ possible_file_formats = _filetypes_from_path (path )
97
+
98
+ for file_format in possible_file_formats :
99
+ if file_format not in reader_map :
100
+ raise ReadError (f"Unknown file format '{ file_format } ' of '{ path } '." )
101
+
102
+ try :
103
+ return reader_map [file_format ](str (path ))
104
+ except ReadError :
105
+ pass
106
+
107
+ error (f"Couldn't read file { path } as either of { ', ' .join (possible_file_formats )} " )
108
+ sys .exit (1 )
109
+
110
+
74
111
def write_points_cells (
75
112
filename ,
76
113
points : ArrayLike ,
@@ -113,10 +150,12 @@ def write(filename, mesh: Mesh, file_format: str | None = None, **kwargs):
113
150
"tetgen format is spread across multiple files, and so cannot be written to a buffer"
114
151
)
115
152
else :
116
- path = pathlib . Path (filename )
153
+ path = Path (filename )
117
154
if not file_format :
118
- # deduce file format from extension
119
- file_format = _filetype_from_path (path )
155
+ # deduce possible file formats from extension
156
+ file_formats = _filetypes_from_path (path )
157
+ # just take the first one
158
+ file_format = file_formats [0 ]
120
159
121
160
try :
122
161
writer = _writer_map [file_format ]
0 commit comments