Skip to content

Commit 305c074

Browse files
RobPasMuepyansys-ci-botpre-commit-ci[bot]
authored
feat: grpc common layer architecture, bodies stub and admin stub implementation (#1867)
Co-authored-by: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 8a5567c commit 305c074

File tree

23 files changed

+2479
-624
lines changed

23 files changed

+2479
-624
lines changed

doc/changelog.d/1867.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
grpc common layer architecture, bodies stub and admin stub implementation

doc/source/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ def intersphinx_pyansys_geometry(switcher_version: str):
279279
"design.grid",
280280
"config.cache",
281281
"design.fa-build",
282+
"toc.not_included", # Caused by the autoapi extension and the "_grpc" folder
282283
]
283284

284285
# Examples gallery customization
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# Copyright (C) 2023 - 2025 ANSYS, Inc. and/or its affiliates.
2+
# SPDX-License-Identifier: MIT
3+
#
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
23+
import grpc
24+
25+
from .._version import GeometryApiProtos, set_proto_version
26+
from .base.bodies import GRPCBodyService
27+
28+
29+
class _GRPCServices:
30+
"""
31+
Placeholder for the gRPC services (i.e. stubs).
32+
33+
Notes
34+
-----
35+
This class provides a unified interface to access the different
36+
gRPC services available in the Geometry API. It allows for easy
37+
switching between different versions of the API by using the
38+
`version` parameter in the constructor. The services are lazy-loaded
39+
to avoid unnecessary imports and to improve performance.
40+
41+
Parameters
42+
----------
43+
channel : grpc.Channel
44+
The gRPC channel to the server.
45+
version : GeometryApiProtos | str | None
46+
The version of the gRPC API protocol to use. If None, the latest
47+
version is used.
48+
"""
49+
50+
def __init__(self, channel: grpc.Channel, version: GeometryApiProtos | str | None = None):
51+
"""
52+
Initialize the GRPCServices class.
53+
54+
Parameters
55+
----------
56+
channel : grpc.Channel
57+
The gRPC channel to the server.
58+
version : GeometryApiProtos | str | None
59+
The version of the gRPC API protocol to use. If None, the latest
60+
version is used.
61+
"""
62+
# Set the proto version to be used
63+
self.version = set_proto_version(channel, version)
64+
self.channel = channel
65+
66+
# Lazy load all the services
67+
self._admin = None
68+
self._bodies = None
69+
70+
@property
71+
def bodies(self) -> GRPCBodyService:
72+
"""
73+
Get the body service for the specified version.
74+
75+
Returns
76+
-------
77+
BodyServiceBase
78+
The body service for the specified version.
79+
"""
80+
if not self._bodies:
81+
# Import the appropriate body service based on the version
82+
from .v0.bodies import GRPCBodyServiceV0
83+
from .v1.bodies import GRPCBodyServiceV1
84+
85+
if self.version == GeometryApiProtos.V0:
86+
self._bodies = GRPCBodyServiceV0(self.channel)
87+
elif self.version == GeometryApiProtos.V1:
88+
self._bodies = GRPCBodyServiceV1(self.channel)
89+
else:
90+
raise ValueError(f"Unsupported version: {self.version}")
91+
92+
return self._bodies
93+
94+
@property
95+
def admin(self):
96+
"""
97+
Get the admin service for the specified version.
98+
99+
Returns
100+
-------
101+
AdminServiceBase
102+
The admin service for the specified version.
103+
"""
104+
if not self._admin:
105+
# Import the appropriate admin service based on the version
106+
from .v0.admin import GRPCAdminServiceV0
107+
from .v1.admin import GRPCAdminServiceV1
108+
109+
if self.version == GeometryApiProtos.V0:
110+
self._admin = GRPCAdminServiceV0(self.channel)
111+
elif self.version == GeometryApiProtos.V1:
112+
self._admin = GRPCAdminServiceV1(self.channel)
113+
else:
114+
raise ValueError(f"Unsupported version: {self.version}")
115+
116+
return self._admin
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Copyright (C) 2023 - 2025 ANSYS, Inc. and/or its affiliates.
2+
# SPDX-License-Identifier: MIT
3+
#
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
"""Module containing the admin service implementation (abstraction layer)."""
23+
24+
from abc import ABC, abstractmethod
25+
26+
import grpc
27+
28+
29+
class GRPCAdminService(ABC):
30+
"""Admin service for gRPC communication with the Geometry server.
31+
32+
Parameters
33+
----------
34+
channel : grpc.Channel
35+
The gRPC channel to the server.
36+
"""
37+
38+
def __init__(self, channel: grpc.Channel):
39+
"""Initialize the AdminServiceBase class."""
40+
pass # pragma: no cover
41+
42+
@abstractmethod
43+
def get_backend(self, **kwargs) -> dict:
44+
"""Get server information."""
45+
pass # pragma: no cover
46+
47+
@abstractmethod
48+
def get_logs(self, **kwargs) -> dict:
49+
"""Get server logs."""
50+
pass # pragma: no cover
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
# Copyright (C) 2023 - 2025 ANSYS, Inc. and/or its affiliates.
2+
# SPDX-License-Identifier: MIT
3+
#
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
"""Module containing the bodies service implementation (abstraction layer)."""
23+
24+
from abc import ABC, abstractmethod
25+
26+
import grpc
27+
28+
29+
class GRPCBodyService(ABC):
30+
"""Body service for gRPC communication with the Geometry server.
31+
32+
Parameters
33+
----------
34+
channel : grpc.Channel
35+
The gRPC channel to the server.
36+
"""
37+
38+
def __init__(self, channel: grpc.Channel):
39+
"""Initialize the BodyServiceBase class."""
40+
pass # pragma: no cover
41+
42+
@abstractmethod
43+
def create_sphere_body(self, **kwargs) -> dict:
44+
"""Create a sphere body."""
45+
pass # pragma: no cover
46+
47+
@abstractmethod
48+
def create_extruded_body(self, **kwargs) -> dict:
49+
"""Create an extruded body."""
50+
pass # pragma: no cover
51+
52+
@abstractmethod
53+
def create_sweeping_profile_body(self, **kwargs) -> dict:
54+
"""Create a sweeping profile body."""
55+
pass # pragma: no cover
56+
57+
@abstractmethod
58+
def create_sweeping_chain(self, **kwargs) -> dict:
59+
"""Create a sweeping chain."""
60+
pass # pragma: no cover
61+
62+
@abstractmethod
63+
def create_extruded_body_from_face_profile(self, **kwargs) -> dict:
64+
"""Create an extruded body from a face profile."""
65+
pass # pragma: no cover
66+
67+
@abstractmethod
68+
def create_extruded_body_from_loft_profiles(self, **kwargs) -> dict:
69+
"""Create an extruded body from loft profiles."""
70+
pass # pragma: no cover
71+
72+
@abstractmethod
73+
def create_planar_body(self, **kwargs) -> dict:
74+
"""Create a planar body."""
75+
pass # pragma: no cover
76+
77+
@abstractmethod
78+
def create_body_from_face(self, **kwargs) -> dict:
79+
"""Create a body from a face."""
80+
pass # pragma: no cover
81+
82+
@abstractmethod
83+
def create_surface_body(self, **kwargs) -> dict:
84+
"""Create a surface body."""
85+
pass # pragma: no cover
86+
87+
@abstractmethod
88+
def create_surface_body_from_trimmed_curves(self, **kwargs) -> dict:
89+
"""Create a surface body from trimmed curves."""
90+
pass # pragma: no cover
91+
92+
@abstractmethod
93+
def translate(self, **kwargs) -> dict:
94+
"""Translate a body."""
95+
pass # pragma: no cover
96+
97+
@abstractmethod
98+
def delete(self, **kwargs) -> dict:
99+
"""Delete a body."""
100+
pass # pragma: no cover
101+
102+
@abstractmethod
103+
def is_suppressed(self, **kwargs) -> dict:
104+
"""Check if a body is suppressed."""
105+
pass # pragma: no cover
106+
107+
@abstractmethod
108+
def get_color(self, **kwargs) -> dict:
109+
"""Get the color of a body."""
110+
pass # pragma: no cover
111+
112+
@abstractmethod
113+
def get_faces(self, **kwargs) -> dict:
114+
"""Get the faces of a body."""
115+
pass # pragma: no cover
116+
117+
@abstractmethod
118+
def get_edges(self, **kwargs) -> dict:
119+
"""Get the edges of a body."""
120+
pass # pragma: no cover
121+
122+
@abstractmethod
123+
def get_volume(self, **kwargs) -> dict:
124+
"""Get the volume of a body."""
125+
pass # pragma: no cover
126+
127+
@abstractmethod
128+
def get_bounding_box(self, **kwargs) -> dict:
129+
"""Get the bounding box of a body."""
130+
pass # pragma: no cover
131+
132+
@abstractmethod
133+
def set_assigned_material(self, **kwargs) -> dict:
134+
"""Set the assigned material of a body."""
135+
pass # pragma: no cover
136+
137+
@abstractmethod
138+
def get_assigned_material(self, **kwargs) -> dict:
139+
"""Get the assigned material of a body."""
140+
pass # pragma: no cover
141+
142+
@abstractmethod
143+
def set_name(self, **kwargs) -> dict:
144+
"""Set the name of a body."""
145+
pass # pragma: no cover
146+
147+
@abstractmethod
148+
def set_fill_style(self, **kwargs) -> dict:
149+
"""Set the fill style of a body."""
150+
pass # pragma: no cover
151+
152+
@abstractmethod
153+
def set_suppressed(self, **kwargs) -> dict:
154+
"""Set the suppressed state of a body."""
155+
pass # pragma: no cover
156+
157+
@abstractmethod
158+
def set_color(self, **kwargs) -> dict:
159+
"""Set the color of a body."""
160+
pass # pragma: no cover
161+
162+
@abstractmethod
163+
def rotate(self, **kwargs) -> dict:
164+
"""Rotate a body."""
165+
pass # pragma: no cover
166+
167+
@abstractmethod
168+
def scale(self, **kwargs) -> dict:
169+
"""Scale a body."""
170+
pass # pragma: no cover
171+
172+
@abstractmethod
173+
def mirror(self, **kwargs) -> dict:
174+
"""Mirror a body."""
175+
pass # pragma: no cover
176+
177+
@abstractmethod
178+
def map(self, **kwargs) -> dict:
179+
"""Map a body."""
180+
pass # pragma: no cover
181+
182+
@abstractmethod
183+
def get_collision(self, **kwargs) -> dict:
184+
"""Get the collision of a body."""
185+
pass # pragma: no cover
186+
187+
@abstractmethod
188+
def copy(self, **kwargs) -> dict:
189+
"""Copy a body."""
190+
pass # pragma: no cover
191+
192+
@abstractmethod
193+
def get_tesellation(self, **kwargs) -> dict:
194+
"""Get the tessellation of a body."""
195+
pass # pragma: no cover
196+
197+
@abstractmethod
198+
def get_tesellation_with_options(self, **kwargs) -> dict:
199+
"""Get the tessellation of a body with options."""
200+
pass # pragma: no cover
201+
202+
@abstractmethod
203+
def boolean(self, **kwargs) -> dict:
204+
"""Boolean operation."""
205+
pass # pragma: no cover

0 commit comments

Comments
 (0)