Skip to content

Commit a153ec6

Browse files
feat: adding deprecation support for args and methods (#1261)
Co-authored-by: pyansys-ci-bot <pyansys.github.bot@ansys.com>
1 parent 9b67df7 commit a153ec6

File tree

8 files changed

+231
-18
lines changed

8 files changed

+231
-18
lines changed

doc/changelog.d/1261.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
feat: adding deprecation support for args and methods

src/ansys/geometry/core/connection/launcher.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
)
3636
from ansys.geometry.core.connection.product_instance import prepare_and_start_backend
3737
from ansys.geometry.core.logger import LOG as logger
38-
from ansys.geometry.core.misc.checks import check_type
38+
from ansys.geometry.core.misc.checks import check_type, deprecated_argument
3939

4040
try:
4141
import ansys.platform.instancemanagement as pypim
@@ -475,6 +475,8 @@ def launch_modeler_with_spaceclaim_and_pimlight(
475475
)
476476

477477

478+
@deprecated_argument(arg="log_level", alternative="server_log_level")
479+
@deprecated_argument(arg="logs_folder", alternative="server_logs_folder")
478480
def launch_modeler_with_geometry_service(
479481
product_version: int = None,
480482
host: str = "localhost",
@@ -600,6 +602,8 @@ def launch_modeler_with_geometry_service(
600602
)
601603

602604

605+
@deprecated_argument(arg="log_level", alternative="server_log_level")
606+
@deprecated_argument(arg="logs_folder", alternative="server_logs_folder")
603607
def launch_modeler_with_discovery(
604608
product_version: int = None,
605609
host: str = "localhost",
@@ -732,6 +736,8 @@ def launch_modeler_with_discovery(
732736
)
733737

734738

739+
@deprecated_argument(arg="log_level", alternative="server_log_level")
740+
@deprecated_argument(arg="logs_folder", alternative="server_logs_folder")
735741
def launch_modeler_with_spaceclaim(
736742
product_version: int = None,
737743
host: str = "localhost",

src/ansys/geometry/core/connection/product_instance.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -263,21 +263,13 @@ def prepare_and_start_backend(
263263
if os.name != "nt": # pragma: no cover
264264
raise RuntimeError("Method 'prepare_and_start_backend' is only available on Windows.")
265265

266-
# Deprecation warnings... To be removed in release 0.7
266+
# Deprecation behavior... To be removed in release 0.7
267267
if log_level is not None: # pragma: no cover
268-
LOG.warning(
269-
"The 'log_level' parameter is deprecated. Please use 'server_log_level' instead."
270-
" The 'log_level' parameter will be removed in the next minor release."
271-
" Overriding 'server_log_level' with 'log_level' value for now..."
272-
)
268+
LOG.warning("Overriding 'server_log_level' with 'log_level' value for now...")
273269
server_log_level = log_level
274270

275271
if logs_folder is not None: # pragma: no cover
276-
LOG.warning(
277-
"The 'logs_folder' parameter is deprecated. Please use 'server_logs_folder' instead."
278-
" The 'logs_folder' parameter will be removed in the next minor release."
279-
" Overriding 'server_logs_folder' with 'logs_folder' value for now..."
280-
)
272+
LOG.warning("Overriding 'server_logs_folder' with 'logs_folder' value for now...")
281273
server_logs_folder = logs_folder
282274

283275
port = _check_port_or_get_one(port)

src/ansys/geometry/core/designer/face.py

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@
4141
from ansys.geometry.core.errors import GeometryRuntimeError, protect_grpc
4242
from ansys.geometry.core.math.point import Point3D
4343
from ansys.geometry.core.math.vector import UnitVector3D
44-
from ansys.geometry.core.misc.checks import ensure_design_is_active, min_backend_version
44+
from ansys.geometry.core.misc.checks import (
45+
deprecated_method,
46+
ensure_design_is_active,
47+
min_backend_version,
48+
)
4549
from ansys.geometry.core.misc.measurements import DEFAULT_UNITS
4650
from ansys.geometry.core.shapes.box_uv import BoxUV
4751
from ansys.geometry.core.shapes.curves.trimmed_curve import TrimmedCurve
@@ -321,6 +325,33 @@ def normal(self, u: float = 0.5, v: float = 0.5) -> UnitVector3D:
321325
response = self._faces_stub.GetNormal(GetNormalRequest(id=self.id, u=u, v=v)).direction
322326
return UnitVector3D([response.x, response.y, response.z])
323327

328+
@deprecated_method(alternative="normal")
329+
def face_normal(self, u: float = 0.5, v: float = 0.5) -> UnitVector3D: # [deprecated-method]
330+
"""
331+
Get the normal direction to the face at certain proportional UV coordinates.
332+
333+
Notes
334+
-----
335+
This method is deprecated. Use the ``normal`` method instead.
336+
337+
Parameters
338+
----------
339+
u : float, default: 0.5
340+
First coordinate of the 2D representation of a surface in UV space.
341+
The default is ``0.5``, which is the center of the surface.
342+
v : float, default: 0.5
343+
Second coordinate of the 2D representation of a surface in UV space.
344+
The default is ``0.5``, which is the center of the surface.
345+
346+
Returns
347+
-------
348+
UnitVector3D
349+
:class:`UnitVector3D` object evaluated at the given U and V coordinates.
350+
This :class:`UnitVector3D` object is perpendicular to the surface at the
351+
given UV coordinates.
352+
"""
353+
return self.normal(u, v)
354+
324355
@protect_grpc
325356
@ensure_design_is_active
326357
def point(self, u: float = 0.5, v: float = 0.5) -> Point3D:
@@ -345,8 +376,7 @@ def point(self, u: float = 0.5, v: float = 0.5) -> Point3D:
345376
Returns
346377
-------
347378
Point3D
348-
:class:`Point3D`
349-
object evaluated at the given UV coordinates.
379+
:class:`Point3D` object evaluated at the given UV coordinates.
350380
"""
351381
try:
352382
return self.shape.evaluate_proportion(u, v).position
@@ -356,6 +386,31 @@ def point(self, u: float = 0.5, v: float = 0.5) -> Point3D:
356386
response = self._faces_stub.Evaluate(EvaluateRequest(id=self.id, u=u, v=v)).point
357387
return Point3D([response.x, response.y, response.z], DEFAULT_UNITS.SERVER_LENGTH)
358388

389+
@deprecated_method(alternative="point")
390+
def face_point(self, u: float = 0.5, v: float = 0.5) -> Point3D:
391+
"""
392+
Get a point of the face evaluated at certain proportional UV coordinates.
393+
394+
Notes
395+
-----
396+
This method is deprecated. Use the ``point`` method instead.
397+
398+
Parameters
399+
----------
400+
u : float, default: 0.5
401+
First coordinate of the 2D representation of a surface in UV space.
402+
The default is ``0.5``, which is the center of the surface.
403+
v : float, default: 0.5
404+
Second coordinate of the 2D representation of a surface in UV space.
405+
The default is ``0.5``, which is the center of the surface.
406+
407+
Returns
408+
-------
409+
Point3D
410+
:class:`Point3D` object evaluated at the given UV coordinates.
411+
"""
412+
return self.point(u, v)
413+
359414
def __grpc_edges_to_edges(self, edges_grpc: List[GRPCEdge]) -> List[Edge]:
360415
"""
361416
Transform a list of gRPC edge messages into actual ``Edge`` objects.

src/ansys/geometry/core/misc/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
check_type,
4242
check_type_all_elements_in_iterable,
4343
check_type_equivalence,
44+
deprecated_argument,
45+
deprecated_method,
4446
min_backend_version,
4547
)
4648
from ansys.geometry.core.misc.measurements import DEFAULT_UNITS, Angle, Distance

src/ansys/geometry/core/misc/checks.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121
# SOFTWARE.
2222
"""Provides functions for performing common checks."""
23+
import warnings
24+
2325
from beartype.typing import TYPE_CHECKING, Any, Iterable, Optional, Tuple, Union
2426
import numpy as np
2527
from pint import Unit
@@ -362,3 +364,65 @@ def wrapper(self, *args, **kwargs):
362364
return wrapper
363365

364366
return backend_version_decorator
367+
368+
369+
def deprecated_method(alternative: Optional[str] = None, info: Optional[str] = None):
370+
"""
371+
Decorate a method as deprecated.
372+
373+
Parameters
374+
----------
375+
alternative : str, default: None
376+
Alternative method to use. If provided, the warning message will
377+
include the alternative method.
378+
info : str, default: None
379+
Additional information to include in the warning message.
380+
"""
381+
382+
def deprecated_decorator(method):
383+
384+
def wrapper(*args, **kwargs):
385+
msg = f"The method '{method.__name__}' is deprecated."
386+
if alternative:
387+
msg += f" Use '{alternative}' instead."
388+
if info:
389+
msg += f" {info}"
390+
warnings.warn(msg, DeprecationWarning)
391+
return method(*args, **kwargs)
392+
393+
return wrapper
394+
395+
return deprecated_decorator
396+
397+
398+
def deprecated_argument(arg: str, alternative: Optional[str] = None, info: Optional[str] = None):
399+
"""
400+
Decorate a method argument as deprecated.
401+
402+
Parameters
403+
----------
404+
arg : str
405+
Argument to mark as deprecated.
406+
alternative : str, default: None
407+
Alternative argument to use. If provided, the warning message will
408+
include the alternative argument.
409+
info : str, default: None
410+
Additional information to include in the warning message.
411+
"""
412+
413+
def deprecated_decorator(method):
414+
415+
def wrapper(*args, **kwargs):
416+
if arg in kwargs and kwargs[arg] is not None:
417+
msg = f"The argument '{arg}' in '{method.__name__}' is deprecated."
418+
if alternative:
419+
msg += f" Use '{alternative}' instead."
420+
if info:
421+
msg += f" {info}"
422+
warnings.warn(msg, DeprecationWarning)
423+
424+
return method(*args, **kwargs)
425+
426+
return wrapper
427+
428+
return deprecated_decorator

src/ansys/geometry/core/plotting/plotter.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121
# SOFTWARE.
2222
"""Provides plotting for various PyAnsys Geometry objects."""
23-
from ansys.tools.visualization_interface import Color, EdgePlot, MeshObjectPlot, Plotter
23+
from ansys.tools.visualization_interface import Color, EdgePlot, MeshObjectPlot
24+
from ansys.tools.visualization_interface import Plotter as PlotterInterface
2425
from ansys.tools.visualization_interface.backends.pyvista import PyVistaBackend
2526
from beartype.typing import Any, Dict, List, Optional, Union
2627
import numpy as np
@@ -35,10 +36,10 @@
3536
from ansys.geometry.core.math.frame import Frame
3637
from ansys.geometry.core.math.plane import Plane
3738
from ansys.geometry.core.plotting.widgets import ShowDesignPoints
38-
from ansys.geometry.core.sketch import Sketch
39+
from ansys.geometry.core.sketch.sketch import Sketch
3940

4041

41-
class GeometryPlotter(Plotter):
42+
class GeometryPlotter(PlotterInterface):
4243
"""
4344
Plotter for PyAnsys Geometry objects.
4445

tests/test_misc_checks.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121
# SOFTWARE.
2222

23+
import warnings
24+
2325
import numpy as np
2426
import pytest
2527

@@ -34,6 +36,8 @@
3436
check_pint_unit_compatibility,
3537
check_type,
3638
check_type_equivalence,
39+
deprecated_argument,
40+
deprecated_method,
3741
min_backend_version,
3842
)
3943

@@ -266,3 +270,91 @@ def case_no_version(mock_object):
266270
match="The method 'case_no_version' requires a minimum Ansys release version of 24.2.0, but the current version used is 24.1.0 or lower.", # noqa: E501
267271
):
268272
case_no_version(mock_object)
273+
274+
275+
def test_deprecated_method_decorator():
276+
"""Test the deprecated method decorator."""
277+
278+
class MockObject:
279+
def __init__(self):
280+
self._grpc_client = None
281+
282+
@staticmethod
283+
@deprecated_method()
284+
def deprecated_method_no_input():
285+
return True
286+
287+
@staticmethod
288+
@deprecated_method(info="This is some extra info.")
289+
def deprecated_method_with_info():
290+
return True
291+
292+
@staticmethod
293+
@deprecated_method(info="This is some extra info.", alternative="new_method")
294+
def deprecated_method_with_info_and_alternate():
295+
return True
296+
297+
mock_object = MockObject()
298+
299+
# Ensure that the method is deprecated
300+
with pytest.deprecated_call(match="The method 'deprecated_method_no_input' is deprecated."):
301+
mock_object.deprecated_method_no_input()
302+
303+
with pytest.deprecated_call(
304+
match="The method 'deprecated_method_with_info' is deprecated. This is some extra info."
305+
):
306+
mock_object.deprecated_method_with_info()
307+
308+
with pytest.deprecated_call(
309+
match="The method 'deprecated_method_with_info_and_alternate' is deprecated."
310+
" Use 'new_method' instead. This is some extra info."
311+
):
312+
mock_object.deprecated_method_with_info_and_alternate()
313+
314+
315+
def test_deprecated_argument_decorator():
316+
"""Test the deprecated argument decorator."""
317+
318+
class MockObject:
319+
def __init__(self):
320+
self._grpc_client = None
321+
322+
@staticmethod
323+
@deprecated_argument("dep_arg")
324+
def deprecated_argument_no_input(dep_arg: str = None):
325+
return True
326+
327+
@staticmethod
328+
@deprecated_argument("dep_arg", info="This is some extra info.")
329+
def deprecated_argument_with_info(dep_arg: str = None):
330+
return True
331+
332+
@staticmethod
333+
@deprecated_argument("dep_arg", info="This is some extra info.", alternative="alt_arg")
334+
def deprecated_argument_with_info_and_alternate(dep_arg: str = None, alt_arg: str = None):
335+
return True
336+
337+
mock_object = MockObject()
338+
339+
# Ensure that the argument is deprecated
340+
with pytest.deprecated_call(
341+
match="The argument 'dep_arg' in 'deprecated_argument_no_input' is deprecated."
342+
):
343+
mock_object.deprecated_argument_no_input(dep_arg="test")
344+
345+
with pytest.deprecated_call(
346+
match="The argument 'dep_arg' in 'deprecated_argument_with_info' is deprecated."
347+
" This is some extra info."
348+
):
349+
mock_object.deprecated_argument_with_info(dep_arg="test")
350+
351+
with pytest.deprecated_call(
352+
match="The argument 'dep_arg' in 'deprecated_argument_with_info_and_alternate'"
353+
" is deprecated. Use 'alt_arg' instead. This is some extra info."
354+
):
355+
mock_object.deprecated_argument_with_info_and_alternate(dep_arg="test")
356+
357+
# Check that if we use the alternative argument, no warning is raised
358+
with warnings.catch_warnings():
359+
warnings.simplefilter("error")
360+
mock_object.deprecated_argument_with_info_and_alternate(alt_arg="test")

0 commit comments

Comments
 (0)