Skip to content

Commit 207ed74

Browse files
RobPasMuepyansys-ci-botpre-commit-ci[bot]
authored
fix: prevent tool and command classes instantiation outside of modeler object (#2188)
Co-authored-by: pyansys-ci-bot <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 24eeafa commit 207ed74

File tree

9 files changed

+167
-19
lines changed

9 files changed

+167
-19
lines changed

doc/changelog.d/2188.fixed.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Prevent tool and command classes instantiation outside of modeler object

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

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
TangentCondition,
7070
)
7171
from ansys.geometry.core.designer.selection import NamedSelection
72-
from ansys.geometry.core.errors import protect_grpc
72+
from ansys.geometry.core.errors import GeometryRuntimeError, protect_grpc
7373
from ansys.geometry.core.math.plane import Plane
7474
from ansys.geometry.core.math.point import Point3D
7575
from ansys.geometry.core.math.vector import UnitVector3D
@@ -135,11 +135,30 @@ class GeometryCommands:
135135
----------
136136
grpc_client : GrpcClient
137137
gRPC client to use for the geometry commands.
138+
_internal_use : bool, optional
139+
Internal flag to prevent direct instantiation by users.
140+
This parameter is for internal use only.
141+
142+
Raises
143+
------
144+
GeometryRuntimeError
145+
If the class is instantiated directly by users instead
146+
of through the modeler.
147+
148+
Notes
149+
-----
150+
This class should not be instantiated directly. Use
151+
``modeler.geometry_commands`` instead.
138152
"""
139153

140154
@protect_grpc
141-
def __init__(self, grpc_client: GrpcClient):
155+
def __init__(self, grpc_client: GrpcClient, _internal_use: bool = False):
142156
"""Initialize an instance of the ``GeometryCommands`` class."""
157+
if not _internal_use:
158+
raise GeometryRuntimeError(
159+
"GeometryCommands should not be instantiated directly. "
160+
"Use 'modeler.geometry_commands' to access geometry commands."
161+
)
143162
self._grpc_client = grpc_client
144163
self._commands_stub = CommandsStub(self._grpc_client.channel)
145164

src/ansys/geometry/core/modeler.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,11 @@ def __init__(
117117
self._design: Optional["Design"] = None
118118

119119
# Enabling tools/commands for all: repair and prepare tools, geometry commands
120-
self._measurement_tools = MeasurementTools(self._grpc_client)
121-
self._repair_tools = RepairTools(self._grpc_client, self)
122-
self._prepare_tools = PrepareTools(self._grpc_client)
123-
self._geometry_commands = GeometryCommands(self._grpc_client)
124-
self._unsupported = UnsupportedCommands(self._grpc_client, self)
120+
self._measurement_tools = MeasurementTools(self._grpc_client, _internal_use=True)
121+
self._repair_tools = RepairTools(self._grpc_client, self, _internal_use=True)
122+
self._prepare_tools = PrepareTools(self._grpc_client, _internal_use=True)
123+
self._geometry_commands = GeometryCommands(self._grpc_client, _internal_use=True)
124+
self._unsupported = UnsupportedCommands(self._grpc_client, self, _internal_use=True)
125125

126126
@property
127127
def client(self) -> GrpcClient:

src/ansys/geometry/core/tools/measurement_tools.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,29 @@ class MeasurementTools:
6060
----------
6161
grpc_client : GrpcClient
6262
gRPC client to use for the measurement tools.
63+
_internal_use : bool, optional
64+
Internal flag to prevent direct instantiation by users.
65+
This parameter is for internal use only.
66+
67+
Raises
68+
------
69+
GeometryRuntimeError
70+
If the class is instantiated directly by users instead
71+
of through the modeler.
72+
73+
Notes
74+
-----
75+
This class should not be instantiated directly. Use
76+
``modeler.measurement_tools`` instead.
6377
"""
6478

65-
def __init__(self, grpc_client: GrpcClient):
79+
def __init__(self, grpc_client: GrpcClient, _internal_use: bool = False):
6680
"""Initialize measurement tools class."""
81+
if not _internal_use:
82+
raise GeometryRuntimeError(
83+
"MeasurementTools should not be instantiated directly. "
84+
"Use 'modeler.measurement_tools' to access measurement tools."
85+
)
6786
self._grpc_client = grpc_client
6887

6988
@min_backend_version(24, 2, 0)

src/ansys/geometry/core/tools/prepare_tools.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
from ansys.geometry.core.connection import GrpcClient
2929
from ansys.geometry.core.connection.backend import BackendType
30+
from ansys.geometry.core.errors import GeometryRuntimeError
3031
from ansys.geometry.core.logger import LOG
3132
from ansys.geometry.core.misc.auxiliary import (
3233
get_bodies_from_ids,
@@ -51,10 +52,28 @@ class PrepareTools:
5152
----------
5253
grpc_client : GrpcClient
5354
Active supporting geometry service instance for design modeling.
55+
_internal_use : bool, optional
56+
Internal flag to prevent direct instantiation by users.
57+
This parameter is for internal use only.
58+
59+
Raises
60+
------
61+
GeometryRuntimeError
62+
If the class is instantiated directly by users instead of through the modeler.
63+
64+
Notes
65+
-----
66+
This class should not be instantiated directly. Use
67+
``modeler.prepare_tools`` instead.
5468
"""
5569

56-
def __init__(self, grpc_client: GrpcClient):
70+
def __init__(self, grpc_client: GrpcClient, _internal_use: bool = False):
5771
"""Initialize Prepare Tools class."""
72+
if not _internal_use:
73+
raise GeometryRuntimeError(
74+
"PrepareTools should not be instantiated directly. "
75+
"Use 'modeler.prepare_tools' to access prepare tools."
76+
)
5877
self._grpc_client = grpc_client
5978

6079
@min_backend_version(25, 1, 0)

src/ansys/geometry/core/tools/repair_tools.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import ansys.geometry.core as pyansys_geometry
2929
from ansys.geometry.core.connection import GrpcClient
30+
from ansys.geometry.core.errors import GeometryRuntimeError
3031
from ansys.geometry.core.misc.auxiliary import (
3132
get_bodies_from_ids,
3233
get_design_from_body,
@@ -61,10 +62,37 @@
6162

6263

6364
class RepairTools:
64-
"""Repair tools for PyAnsys Geometry."""
65-
66-
def __init__(self, grpc_client: GrpcClient, modeler: "Modeler"):
65+
"""Repair tools for PyAnsys Geometry.
66+
67+
Parameters
68+
----------
69+
grpc_client : GrpcClient
70+
Active supporting geometry service instance for design modeling.
71+
modeler : Modeler
72+
The parent modeler instance.
73+
_internal_use : bool, optional
74+
Internal flag to prevent direct instantiation by users.
75+
This parameter is for internal use only.
76+
77+
Raises
78+
------
79+
GeometryRuntimeError
80+
If the class is instantiated directly by users instead
81+
of through the modeler.
82+
83+
Notes
84+
-----
85+
This class should not be instantiated directly. Use
86+
``modeler.repair_tools`` instead.
87+
"""
88+
89+
def __init__(self, grpc_client: GrpcClient, modeler: "Modeler", _internal_use: bool = False):
6790
"""Initialize a new instance of the ``RepairTools`` class."""
91+
if not _internal_use:
92+
raise GeometryRuntimeError(
93+
"RepairTools should not be instantiated directly. "
94+
"Use 'modeler.repair_tools' to access repair tools."
95+
)
6896
self._modeler = modeler
6997
self._grpc_client = grpc_client
7098

src/ansys/geometry/core/tools/unsupported.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
)
3434
from ansys.api.geometry.v0.unsupported_pb2_grpc import UnsupportedStub
3535
from ansys.geometry.core.connection import GrpcClient
36-
from ansys.geometry.core.errors import protect_grpc
36+
from ansys.geometry.core.errors import GeometryRuntimeError, protect_grpc
3737
from ansys.geometry.core.misc.auxiliary import get_all_bodies_from_design
3838
from ansys.geometry.core.misc.checks import (
3939
min_backend_version,
@@ -72,10 +72,29 @@ class UnsupportedCommands:
7272
gRPC client to use for the geometry commands.
7373
modeler : Modeler
7474
Modeler instance to use for the geometry commands.
75+
_internal_use : bool, optional
76+
Internal flag to prevent direct instantiation by users.
77+
This parameter is for internal use only.
78+
79+
Raises
80+
------
81+
GeometryRuntimeError
82+
If the class is instantiated directly by users instead of through the modeler.
83+
84+
Notes
85+
-----
86+
This class should not be instantiated directly. Use
87+
``modeler.unsupported`` instead.
88+
7589
"""
7690

77-
def __init__(self, grpc_client: GrpcClient, modeler: "Modeler"):
91+
def __init__(self, grpc_client: GrpcClient, modeler: "Modeler", _internal_use: bool = False):
7892
"""Initialize an instance of the ``UnsupportedCommands`` class."""
93+
if not _internal_use:
94+
raise GeometryRuntimeError(
95+
"UnsupportedCommands should not be instantiated directly. "
96+
"Use 'modeler.unsupported' to access unsupported commands."
97+
)
7998
self._grpc_client = grpc_client
8099
self._unsupported_stub = UnsupportedStub(self._grpc_client.channel)
81100
self.__id_map = {}

tests/integration/test_issues.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@
2424
from pathlib import Path
2525

2626
import numpy as np
27+
import pytest
2728

29+
from ansys.geometry.core.designer.geometry_commands import GeometryCommands
30+
from ansys.geometry.core.errors import GeometryRuntimeError
2831
from ansys.geometry.core.math import (
2932
UNITVECTOR3D_X,
3033
UNITVECTOR3D_Y,
@@ -37,6 +40,12 @@
3740
from ansys.geometry.core.misc import DEFAULT_UNITS, UNITS, Angle, Distance
3841
from ansys.geometry.core.modeler import Modeler
3942
from ansys.geometry.core.sketch import Sketch
43+
from ansys.geometry.core.tools import (
44+
MeasurementTools,
45+
PrepareTools,
46+
RepairTools,
47+
UnsupportedCommands,
48+
)
4049

4150
from .conftest import FILES_DIR
4251

@@ -325,3 +334,40 @@ def test_issue_1813_edge_start_end_non_default_units(modeler: Modeler):
325334
finally:
326335
# Reset the default units to meters
327336
DEFAULT_UNITS.LENGTH = UNITS.meter
337+
338+
339+
def test_issue_2184_prevent_raw_instantiation_of_tools_and_commands():
340+
"""Test that raw instantiation of tools and commands is prevented.
341+
342+
For more info see
343+
https://github.com/ansys/pyansys-geometry/issues/2184
344+
"""
345+
# Test UnsupportedCommands
346+
with pytest.raises(
347+
GeometryRuntimeError, match="UnsupportedCommands should not be instantiated directly"
348+
):
349+
UnsupportedCommands(None, None)
350+
351+
# Test RepairTools
352+
with pytest.raises(
353+
GeometryRuntimeError, match="RepairTools should not be instantiated directly"
354+
):
355+
RepairTools(None, None)
356+
357+
# Test PrepareTools
358+
with pytest.raises(
359+
GeometryRuntimeError, match="PrepareTools should not be instantiated directly"
360+
):
361+
PrepareTools(None)
362+
363+
# Test MeasurementTools
364+
with pytest.raises(
365+
GeometryRuntimeError, match="MeasurementTools should not be instantiated directly"
366+
):
367+
MeasurementTools(None)
368+
369+
# Test GeometryCommands
370+
with pytest.raises(
371+
GeometryRuntimeError, match="GeometryCommands should not be instantiated directly"
372+
):
373+
GeometryCommands(None)

tests/integration/test_repair_tools.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
UnsimplifiedFaceProblemAreas,
3939
)
4040
from ansys.geometry.core.tools.repair_tool_message import RepairToolMessage
41-
from ansys.geometry.core.tools.repair_tools import RepairTools
4241

4342
from .conftest import FILES_DIR
4443

@@ -731,8 +730,7 @@ def test_problem_area_fix_no_data(modeler: Modeler, problem_area_class, kwargs):
731730
)
732731
def test_repair_tools_no_bodies(modeler: Modeler, method_name):
733732
"""Test RepairTools methods when bodies is empty or None."""
734-
grpc_client = modeler.client
735-
repair_tools = RepairTools(grpc_client, modeler)
733+
repair_tools = modeler.repair_tools
736734
method = getattr(repair_tools, method_name)
737735

738736
# Test with an empty list of bodies
@@ -755,8 +753,7 @@ def test_repair_tools_no_bodies(modeler: Modeler, method_name):
755753
)
756754
def test_repair_tools_find_and_fix_no_bodies(modeler: Modeler, method_name):
757755
"""Test RepairTools find_and_fix methods when bodies is empty or None."""
758-
grpc_client = modeler.client
759-
repair_tools = RepairTools(grpc_client, modeler)
756+
repair_tools = modeler.repair_tools
760757
method = getattr(repair_tools, method_name)
761758

762759
# Test with an empty list of bodies

0 commit comments

Comments
 (0)