mmgpy 0.5.0__cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. mmgpy/__init__.py +296 -0
  2. mmgpy/__main__.py +13 -0
  3. mmgpy/_io.py +535 -0
  4. mmgpy/_logging.py +290 -0
  5. mmgpy/_mesh.py +2286 -0
  6. mmgpy/_mmgpy.cpython-311-x86_64-linux-gnu.so +0 -0
  7. mmgpy/_mmgpy.pyi +2140 -0
  8. mmgpy/_options.py +304 -0
  9. mmgpy/_progress.py +850 -0
  10. mmgpy/_pyvista.py +410 -0
  11. mmgpy/_result.py +143 -0
  12. mmgpy/_transfer.py +273 -0
  13. mmgpy/_validation.py +669 -0
  14. mmgpy/_version.py +3 -0
  15. mmgpy/_version.py.in +3 -0
  16. mmgpy/bin/mmg2d_O3 +0 -0
  17. mmgpy/bin/mmg3d_O3 +0 -0
  18. mmgpy/bin/mmgs_O3 +0 -0
  19. mmgpy/interactive/__init__.py +24 -0
  20. mmgpy/interactive/sizing_editor.py +790 -0
  21. mmgpy/lagrangian.py +394 -0
  22. mmgpy/lib/libmmg2d.so +0 -0
  23. mmgpy/lib/libmmg2d.so.5 +0 -0
  24. mmgpy/lib/libmmg2d.so.5.8.0 +0 -0
  25. mmgpy/lib/libmmg3d.so +0 -0
  26. mmgpy/lib/libmmg3d.so.5 +0 -0
  27. mmgpy/lib/libmmg3d.so.5.8.0 +0 -0
  28. mmgpy/lib/libmmgs.so +0 -0
  29. mmgpy/lib/libmmgs.so.5 +0 -0
  30. mmgpy/lib/libmmgs.so.5.8.0 +0 -0
  31. mmgpy/lib/libvtkCommonColor-9.5.so.1 +0 -0
  32. mmgpy/lib/libvtkCommonComputationalGeometry-9.5.so.1 +0 -0
  33. mmgpy/lib/libvtkCommonCore-9.5.so.1 +0 -0
  34. mmgpy/lib/libvtkCommonDataModel-9.5.so.1 +0 -0
  35. mmgpy/lib/libvtkCommonExecutionModel-9.5.so.1 +0 -0
  36. mmgpy/lib/libvtkCommonMath-9.5.so.1 +0 -0
  37. mmgpy/lib/libvtkCommonMisc-9.5.so.1 +0 -0
  38. mmgpy/lib/libvtkCommonSystem-9.5.so.1 +0 -0
  39. mmgpy/lib/libvtkCommonTransforms-9.5.so.1 +0 -0
  40. mmgpy/lib/libvtkDICOMParser-9.5.so.1 +0 -0
  41. mmgpy/lib/libvtkFiltersCellGrid-9.5.so.1 +0 -0
  42. mmgpy/lib/libvtkFiltersCore-9.5.so.1 +0 -0
  43. mmgpy/lib/libvtkFiltersExtraction-9.5.so.1 +0 -0
  44. mmgpy/lib/libvtkFiltersGeneral-9.5.so.1 +0 -0
  45. mmgpy/lib/libvtkFiltersGeometry-9.5.so.1 +0 -0
  46. mmgpy/lib/libvtkFiltersHybrid-9.5.so.1 +0 -0
  47. mmgpy/lib/libvtkFiltersHyperTree-9.5.so.1 +0 -0
  48. mmgpy/lib/libvtkFiltersModeling-9.5.so.1 +0 -0
  49. mmgpy/lib/libvtkFiltersParallel-9.5.so.1 +0 -0
  50. mmgpy/lib/libvtkFiltersReduction-9.5.so.1 +0 -0
  51. mmgpy/lib/libvtkFiltersSources-9.5.so.1 +0 -0
  52. mmgpy/lib/libvtkFiltersStatistics-9.5.so.1 +0 -0
  53. mmgpy/lib/libvtkFiltersTexture-9.5.so.1 +0 -0
  54. mmgpy/lib/libvtkFiltersVerdict-9.5.so.1 +0 -0
  55. mmgpy/lib/libvtkIOCellGrid-9.5.so.1 +0 -0
  56. mmgpy/lib/libvtkIOCore-9.5.so.1 +0 -0
  57. mmgpy/lib/libvtkIOGeometry-9.5.so.1 +0 -0
  58. mmgpy/lib/libvtkIOImage-9.5.so.1 +0 -0
  59. mmgpy/lib/libvtkIOLegacy-9.5.so.1 +0 -0
  60. mmgpy/lib/libvtkIOParallel-9.5.so.1 +0 -0
  61. mmgpy/lib/libvtkIOParallelXML-9.5.so.1 +0 -0
  62. mmgpy/lib/libvtkIOXML-9.5.so.1 +0 -0
  63. mmgpy/lib/libvtkIOXMLParser-9.5.so.1 +0 -0
  64. mmgpy/lib/libvtkImagingCore-9.5.so.1 +0 -0
  65. mmgpy/lib/libvtkImagingSources-9.5.so.1 +0 -0
  66. mmgpy/lib/libvtkParallelCore-9.5.so.1 +0 -0
  67. mmgpy/lib/libvtkParallelDIY-9.5.so.1 +0 -0
  68. mmgpy/lib/libvtkRenderingCore-9.5.so.1 +0 -0
  69. mmgpy/lib/libvtkdoubleconversion-9.5.so.1 +0 -0
  70. mmgpy/lib/libvtkexpat-9.5.so.1 +0 -0
  71. mmgpy/lib/libvtkfmt-9.5.so.1 +0 -0
  72. mmgpy/lib/libvtkjpeg-9.5.so.1 +0 -0
  73. mmgpy/lib/libvtkjsoncpp-9.5.so.1 +0 -0
  74. mmgpy/lib/libvtkkissfft-9.5.so.1 +0 -0
  75. mmgpy/lib/libvtkloguru-9.5.so.1 +0 -0
  76. mmgpy/lib/libvtklz4-9.5.so.1 +0 -0
  77. mmgpy/lib/libvtklzma-9.5.so.1 +0 -0
  78. mmgpy/lib/libvtkmetaio-9.5.so.1 +0 -0
  79. mmgpy/lib/libvtkpng-9.5.so.1 +0 -0
  80. mmgpy/lib/libvtkpugixml-9.5.so.1 +0 -0
  81. mmgpy/lib/libvtksys-9.5.so.1 +0 -0
  82. mmgpy/lib/libvtktiff-9.5.so.1 +0 -0
  83. mmgpy/lib/libvtktoken-9.5.so.1 +0 -0
  84. mmgpy/lib/libvtkverdict-9.5.so.1 +0 -0
  85. mmgpy/lib/libvtkzlib-9.5.so.1 +0 -0
  86. mmgpy/metrics.py +596 -0
  87. mmgpy/progress.py +69 -0
  88. mmgpy/py.typed +0 -0
  89. mmgpy/repair/__init__.py +37 -0
  90. mmgpy/repair/_core.py +226 -0
  91. mmgpy/repair/_elements.py +241 -0
  92. mmgpy/repair/_vertices.py +219 -0
  93. mmgpy/sizing.py +370 -0
  94. mmgpy/ui/__init__.py +97 -0
  95. mmgpy/ui/__main__.py +87 -0
  96. mmgpy/ui/app.py +1837 -0
  97. mmgpy/ui/parsers.py +501 -0
  98. mmgpy/ui/remeshing.py +448 -0
  99. mmgpy/ui/samples.py +249 -0
  100. mmgpy/ui/utils.py +280 -0
  101. mmgpy/ui/viewer.py +587 -0
  102. mmgpy-0.5.0.dist-info/METADATA +186 -0
  103. mmgpy-0.5.0.dist-info/RECORD +109 -0
  104. mmgpy-0.5.0.dist-info/WHEEL +6 -0
  105. mmgpy-0.5.0.dist-info/entry_points.txt +13 -0
  106. mmgpy-0.5.0.dist-info/licenses/LICENSE +38 -0
  107. share/man/man1/mmg2d.1.gz +0 -0
  108. share/man/man1/mmg3d.1.gz +0 -0
  109. share/man/man1/mmgs.1.gz +0 -0
mmgpy/_logging.py ADDED
@@ -0,0 +1,290 @@
1
+ """Logging configuration for mmgpy with Rich integration and file logging support."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import functools
6
+ import logging
7
+ import os
8
+ from logging.handlers import RotatingFileHandler
9
+ from pathlib import Path
10
+ from typing import TYPE_CHECKING
11
+
12
+ from rich.logging import RichHandler
13
+
14
+ if TYPE_CHECKING:
15
+ from typing import Literal
16
+
17
+ LogLevel = Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
18
+
19
+ # Module-level state for file handler
20
+ _file_handler: RotatingFileHandler | None = None
21
+
22
+ # Track whether console handler is enabled
23
+ _console_enabled: bool = True
24
+
25
+
26
+ @functools.lru_cache(maxsize=1)
27
+ def get_logger() -> logging.Logger:
28
+ """Get or create the mmgpy logger.
29
+
30
+ This returns the underlying logger instance, which can be used for:
31
+ - Direct logging calls
32
+ - Integration with external logging frameworks
33
+ - Custom handler configuration
34
+
35
+ Returns
36
+ -------
37
+ logging.Logger
38
+ The mmgpy logger instance.
39
+
40
+ Examples
41
+ --------
42
+ >>> import mmgpy
43
+ >>> logger = mmgpy.get_logger()
44
+ >>> logger.info("Custom message")
45
+
46
+ Integration with external loggers:
47
+
48
+ >>> import logging
49
+ >>> # Configure your own handler before importing mmgpy
50
+ >>> handler = logging.StreamHandler()
51
+ >>> handler.setFormatter(logging.Formatter('%(name)s - %(message)s'))
52
+ >>>
53
+ >>> import mmgpy
54
+ >>> mmgpy.configure_logging(enable_console=False) # Disable Rich
55
+ >>> mmgpy.get_logger().addHandler(handler) # Use your own handler
56
+
57
+ """
58
+ logger = logging.getLogger("mmgpy")
59
+
60
+ if not logger.handlers:
61
+ _configure_logger(logger)
62
+
63
+ return logger
64
+
65
+
66
+ def _configure_logger(logger: logging.Logger) -> None:
67
+ """Configure the logger with RichHandler."""
68
+ if _console_enabled:
69
+ handler = RichHandler(
70
+ rich_tracebacks=True,
71
+ show_path=False,
72
+ markup=True,
73
+ )
74
+ handler.setFormatter(logging.Formatter("%(message)s"))
75
+ logger.addHandler(handler)
76
+
77
+ if os.environ.get("MMGPY_DEBUG"):
78
+ logger.setLevel(logging.DEBUG)
79
+ else:
80
+ logger.setLevel(logging.WARNING)
81
+
82
+
83
+ def configure_logging(*, enable_console: bool = True) -> None:
84
+ """Configure mmgpy logging behavior.
85
+
86
+ This function allows customization of mmgpy's logging setup,
87
+ particularly useful when integrating with external logging frameworks.
88
+
89
+ Parameters
90
+ ----------
91
+ enable_console : bool, default True
92
+ Whether to enable the default Rich console handler.
93
+ Set to False when using your own logging handlers.
94
+
95
+ Notes
96
+ -----
97
+ This function should be called BEFORE any other mmgpy operations
98
+ if you want to disable the default console handler. Once the logger
99
+ is initialized, use `get_logger()` to add your own handlers.
100
+
101
+ Examples
102
+ --------
103
+ Using mmgpy with a custom logging setup:
104
+
105
+ >>> import mmgpy
106
+ >>> # Disable default Rich handler
107
+ >>> mmgpy.configure_logging(enable_console=False)
108
+ >>>
109
+ >>> # Add your own handler
110
+ >>> import logging
111
+ >>> handler = logging.FileHandler("app.log")
112
+ >>> handler.setFormatter(logging.Formatter(
113
+ ... '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
114
+ ... ))
115
+ >>> mmgpy.get_logger().addHandler(handler)
116
+
117
+ Integration with structlog or loguru:
118
+
119
+ >>> import mmgpy
120
+ >>> mmgpy.configure_logging(enable_console=False)
121
+ >>> # Now configure your preferred logging library
122
+ >>> # mmgpy logs will go to the "mmgpy" logger namespace
123
+
124
+ """
125
+ global _console_enabled # noqa: PLW0603
126
+ logger = logging.getLogger("mmgpy")
127
+
128
+ if not enable_console:
129
+ _console_enabled = False
130
+ # Remove existing Rich handlers if logger already initialized
131
+ for handler in logger.handlers[:]:
132
+ if isinstance(handler, RichHandler):
133
+ logger.removeHandler(handler)
134
+ handler.close()
135
+
136
+
137
+ def set_log_file(
138
+ path: str | Path | None,
139
+ max_bytes: int = 10_000_000,
140
+ backup_count: int = 5,
141
+ level: int | str | None = None,
142
+ ) -> None:
143
+ """Configure file logging for mmgpy.
144
+
145
+ Enables logging to a file with optional rotation. This can be used
146
+ alongside console logging - logs will go to both destinations.
147
+
148
+ Parameters
149
+ ----------
150
+ path : str | Path | None
151
+ Log file path, or None to disable file logging.
152
+ max_bytes : int, default 10_000_000
153
+ Maximum file size in bytes before rotation (default 10 MB).
154
+ Set to 0 to disable rotation.
155
+ backup_count : int, default 5
156
+ Number of backup files to keep after rotation.
157
+ level : int | str | None, default None
158
+ Logging level for the file handler. Can be a string like "DEBUG"
159
+ or an integer constant from the logging module.
160
+ If None, uses the same level as the logger.
161
+
162
+ Examples
163
+ --------
164
+ Basic file logging:
165
+
166
+ >>> import mmgpy
167
+ >>> mmgpy.set_log_file("mmgpy.log")
168
+ >>> mesh = mmgpy.read("input.mesh")
169
+ >>> mesh.remesh(hmax=0.1, verbose=1) # Output goes to file and console
170
+
171
+ With rotation settings:
172
+
173
+ >>> mmgpy.set_log_file(
174
+ ... "mmgpy.log",
175
+ ... max_bytes=5_000_000, # 5 MB
176
+ ... backup_count=3
177
+ ... )
178
+
179
+ Debug level for file only (console stays at WARNING):
180
+
181
+ >>> mmgpy.set_log_file("debug.log", level="DEBUG")
182
+
183
+ Disable file logging:
184
+
185
+ >>> mmgpy.set_log_file(None)
186
+
187
+ """
188
+ global _file_handler # noqa: PLW0603
189
+ logger = get_logger()
190
+
191
+ # Remove existing file handler
192
+ if _file_handler is not None:
193
+ logger.removeHandler(_file_handler)
194
+ _file_handler.close()
195
+ _file_handler = None
196
+
197
+ if path is None:
198
+ return
199
+
200
+ # Create parent directories if needed
201
+ path = Path(path)
202
+ path.parent.mkdir(parents=True, exist_ok=True)
203
+
204
+ # Create new file handler with rotation
205
+ _file_handler = RotatingFileHandler(
206
+ path,
207
+ maxBytes=max_bytes,
208
+ backupCount=backup_count,
209
+ )
210
+
211
+ # Set formatter for file output (more detailed than console)
212
+ formatter = logging.Formatter(
213
+ "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
214
+ )
215
+ _file_handler.setFormatter(formatter)
216
+
217
+ # Set level for file handler
218
+ # Use NOTSET (0) by default so handler defers to logger's level
219
+ if level is not None:
220
+ if isinstance(level, str):
221
+ level = getattr(logging, level.upper())
222
+ _file_handler.setLevel(level)
223
+ else:
224
+ _file_handler.setLevel(logging.NOTSET)
225
+
226
+ logger.addHandler(_file_handler)
227
+
228
+
229
+ def get_log_file() -> Path | None:
230
+ """Get the current log file path.
231
+
232
+ Returns
233
+ -------
234
+ Path | None
235
+ The current log file path, or None if file logging is disabled.
236
+
237
+ Examples
238
+ --------
239
+ >>> import mmgpy
240
+ >>> mmgpy.set_log_file("output.log")
241
+ >>> print(mmgpy.get_log_file())
242
+ output.log
243
+ >>> mmgpy.set_log_file(None)
244
+ >>> print(mmgpy.get_log_file())
245
+ None
246
+
247
+ """
248
+ if _file_handler is None:
249
+ return None
250
+ return Path(_file_handler.baseFilename)
251
+
252
+
253
+ def set_log_level(level: LogLevel | int) -> None:
254
+ """Set the logging level for mmgpy.
255
+
256
+ This sets the level for the logger itself. Individual handlers
257
+ (console, file) may have their own levels set separately.
258
+
259
+ Parameters
260
+ ----------
261
+ level : LogLevel | int
262
+ The logging level. Can be a string like "DEBUG", "INFO", "WARNING",
263
+ "ERROR", "CRITICAL" or an integer constant from the logging module.
264
+
265
+ Examples
266
+ --------
267
+ >>> import mmgpy
268
+ >>> mmgpy.set_log_level("DEBUG") # Show all debug messages
269
+ >>> mmgpy.set_log_level("INFO") # Show info and above
270
+ >>> mmgpy.set_log_level("WARNING") # Default - show warnings and errors
271
+
272
+ """
273
+ logger = get_logger()
274
+ if isinstance(level, str):
275
+ level = getattr(logging, level.upper())
276
+ logger.setLevel(level)
277
+
278
+
279
+ def enable_debug() -> None:
280
+ """Enable debug logging for mmgpy.
281
+
282
+ This is equivalent to calling `set_log_level("DEBUG")` or setting
283
+ the `MMGPY_DEBUG` environment variable.
284
+ """
285
+ set_log_level(logging.DEBUG)
286
+
287
+
288
+ def disable_logging() -> None:
289
+ """Disable all logging output from mmgpy."""
290
+ set_log_level(logging.CRITICAL + 1)