Skip to content

Commit 61bffdd

Browse files
jacobrkerstetterpre-commit-ci[bot]pyansys-ci-botRobPasMue
authored
chore: v1 implementation of admin and assembly condition stubs (#2391)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: pyansys-ci-bot <[email protected]> Co-authored-by: Roberto Pastor Muela <[email protected]>
1 parent 454f13e commit 61bffdd

File tree

9 files changed

+338
-96
lines changed

9 files changed

+338
-96
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
V1 implementation of admin and assembly condition stubs

src/ansys/geometry/core/_grpc/_services/_service.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
from .._version import GeometryApiProtos, set_proto_version
2626
from .base.admin import GRPCAdminService
27-
from .base.assembly_controls import GRPCAssemblyControlsService
27+
from .base.assembly_condition import GRPCAssemblyConditionService
2828
from .base.beams import GRPCBeamsService
2929
from .base.bodies import GRPCBodyService
3030
from .base.commands import GRPCCommandsService
@@ -87,7 +87,7 @@ def __init__(self, channel: grpc.Channel, version: GeometryApiProtos | str | Non
8787

8888
# Lazy load all the services
8989
self._admin = None
90-
self._assembly_controls = None
90+
self._assembly_condition = None
9191
self._beams = None
9292
self._bodies = None
9393
self._commands = None
@@ -137,30 +137,30 @@ def admin(self) -> GRPCAdminService:
137137
return self._admin
138138

139139
@property
140-
def assembly_controls(self) -> GRPCAssemblyControlsService:
140+
def assembly_condition(self) -> GRPCAssemblyConditionService:
141141
"""
142-
Get the assembly controls service for the specified version.
142+
Get the assembly condition service for the specified version.
143143
144144
Returns
145145
-------
146-
GRPCAssemblyControlsService
147-
The assembly controls service for the specified version.
146+
GRPCAssemblyConditionService
147+
The assembly condition service for the specified version.
148148
"""
149-
if not self._assembly_controls:
150-
# Import the appropriate assembly controls service based on the version
151-
from .v0.assembly_controls import GRPCAssemblyControlsServiceV0
152-
from .v1.assembly_controls import GRPCAssemblyControlsServiceV1
149+
if not self._assembly_condition:
150+
# Import the appropriate assembly condition service based on the version
151+
from .v0.assembly_condition import GRPCAssemblyConditionServiceV0
152+
from .v1.assembly_condition import GRPCAssemblyConditionServiceV1
153153

154154
if self.version == GeometryApiProtos.V0:
155-
self._assembly_controls = GRPCAssemblyControlsServiceV0(self.channel)
155+
self._assembly_condition = GRPCAssemblyConditionServiceV0(self.channel)
156156
elif self.version == GeometryApiProtos.V1: # pragma: no cover
157157
# V1 is not implemented yet
158-
self._assembly_controls = GRPCAssemblyControlsServiceV1(self.channel)
158+
self._assembly_condition = GRPCAssemblyConditionServiceV1(self.channel)
159159
else: # pragma: no cover
160160
# This should never happen as the version is set in the constructor
161161
raise ValueError(f"Unsupported version: {self.version}")
162162

163-
return self._assembly_controls
163+
return self._assembly_condition
164164

165165
@property
166166
def beams(self) -> GRPCBeamsService:

src/ansys/geometry/core/_grpc/_services/base/assembly_controls.py renamed to src/ansys/geometry/core/_grpc/_services/base/assembly_condition.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@
1919
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2020
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121
# SOFTWARE.
22-
"""Module containing the assembly controls service implementation (abstraction layer)."""
22+
"""Module containing the assembly condition service implementation (abstraction layer)."""
2323

2424
from abc import ABC, abstractmethod
2525

2626
import grpc
2727

2828

29-
class GRPCAssemblyControlsService(ABC): # pragma: no cover
30-
"""Assembly controls service for gRPC communication with the Geometry server.
29+
class GRPCAssemblyConditionService(ABC): # pragma: no cover
30+
"""Assembly condition service for gRPC communication with the Geometry server.
3131
3232
Parameters
3333
----------
@@ -36,7 +36,7 @@ class GRPCAssemblyControlsService(ABC): # pragma: no cover
3636
"""
3737

3838
def __init__(self, channel: grpc.Channel):
39-
"""Initialize the GRPCAssemblyControls class."""
39+
"""Initialize the GRPCAssemblyCondition class."""
4040
pass
4141

4242
@abstractmethod

src/ansys/geometry/core/_grpc/_services/v0/assembly_controls.py renamed to src/ansys/geometry/core/_grpc/_services/v0/assembly_condition.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,21 @@
1919
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2020
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121
# SOFTWARE.
22-
"""Module containing the assembly controls service implementation for v0."""
22+
"""Module containing the assembly condition service implementation for v0."""
2323

2424
import grpc
2525

2626
from ansys.geometry.core.errors import protect_grpc
2727

28-
from ..base.assembly_controls import GRPCAssemblyControlsService
28+
from ..base.assembly_condition import GRPCAssemblyConditionService
2929
from .conversions import build_grpc_id
3030

3131

32-
class GRPCAssemblyControlsServiceV0(GRPCAssemblyControlsService):
33-
"""Assembly controls service for gRPC communication with the Geometry server.
32+
class GRPCAssemblyConditionServiceV0(GRPCAssemblyConditionService):
33+
"""Assembly condition service for gRPC communication with the Geometry server.
3434
3535
This class provides methods to interact with the Geometry server's
36-
assembly controls service. It is specifically designed for the v0 version of the
36+
assembly condition service. It is specifically designed for the v0 version of the
3737
Geometry API.
3838
3939
Parameters
@@ -66,7 +66,7 @@ def create_align_condition(self, **kwargs) -> dict: # noqa: D102
6666

6767
# Return the response - formatted as a dictionary
6868
return {
69-
"moniker": resp.condition.moniker,
69+
"id": resp.condition.moniker,
7070
"is_deleted": resp.condition.is_deleted,
7171
"is_enabled": resp.condition.is_enabled,
7272
"is_satisfied": resp.condition.is_satisfied,
@@ -93,7 +93,7 @@ def create_tangent_condition(self, **kwargs) -> dict: # noqa: D102
9393

9494
# Return the response - formatted as a dictionary
9595
return {
96-
"moniker": resp.condition.moniker,
96+
"id": resp.condition.moniker,
9797
"is_deleted": resp.condition.is_deleted,
9898
"is_enabled": resp.condition.is_enabled,
9999
"is_satisfied": resp.condition.is_satisfied,
@@ -120,7 +120,7 @@ def create_orient_condition(self, **kwargs) -> dict: # noqa: D102
120120

121121
# Return the response - formatted as a dictionary
122122
return {
123-
"moniker": resp.condition.moniker,
123+
"id": resp.condition.moniker,
124124
"is_deleted": resp.condition.is_deleted,
125125
"is_enabled": resp.condition.is_enabled,
126126
"is_satisfied": resp.condition.is_satisfied,

src/ansys/geometry/core/_grpc/_services/v1/admin.py

Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,15 @@
2121
# SOFTWARE.
2222
"""Module containing the admin service implementation for v1."""
2323

24+
import warnings
25+
2426
import grpc
27+
import semver
2528

2629
from ansys.geometry.core.errors import protect_grpc
2730

2831
from ..base.admin import GRPCAdminService
32+
from .conversions import from_grpc_backend_type_to_backend_type
2933

3034

3135
class GRPCAdminServiceV1(GRPCAdminService): # pragma: no cover
@@ -43,18 +47,82 @@ class GRPCAdminServiceV1(GRPCAdminService): # pragma: no cover
4347

4448
@protect_grpc
4549
def __init__(self, channel: grpc.Channel): # noqa: D102
46-
from ansys.api.dbu.v1.admin_pb2_grpc import AdminStub
50+
from ansys.api.discovery.v1.commands.application_pb2_grpc import ApplicationStub
51+
from ansys.api.discovery.v1.commands.communication_pb2_grpc import CommunicationStub
4752

48-
self.stub = AdminStub(channel)
53+
self.admin_stub = ApplicationStub(channel)
54+
self.communication_stub = CommunicationStub(channel)
4955

5056
@protect_grpc
5157
def get_backend(self, **kwargs) -> dict: # noqa: D102
52-
raise NotImplementedError
58+
# TODO: Remove this context and filter once the protobuf UserWarning is downgraded to INFO
59+
# https://github.com/grpc/grpc/issues/37609
60+
with warnings.catch_warnings():
61+
warnings.filterwarnings(
62+
"ignore", "Protobuf gencode version", UserWarning, "google.protobuf.runtime_version"
63+
)
64+
from ansys.api.discovery.v1.commands.application_pb2 import GetBackendRequest
65+
66+
# Create the request - assumes all inputs are valid and of the proper type
67+
request = GetBackendRequest()
68+
69+
# Call the gRPC service
70+
response = self.admin_stub.GetBackend(request=request)
71+
72+
ver = response.version
73+
backend_version = semver.Version(ver.major_release, ver.minor_release, ver.service_pack)
74+
api_server_build_info = f"{ver.build_number}" if ver.build_number != 0 else "N/A"
75+
product_build_info = (
76+
response.backend_version_info.strip() if response.backend_version_info else "N/A"
77+
)
78+
79+
# Convert the response to a dictionary
80+
return {
81+
"backend": from_grpc_backend_type_to_backend_type(response.type),
82+
"version": backend_version,
83+
"api_server_build_info": api_server_build_info,
84+
"product_build_info": product_build_info,
85+
"additional_info": {k: v for k, v in response.additional_build_info.items()},
86+
}
5387

5488
@protect_grpc
5589
def get_logs(self, **kwargs) -> dict: # noqa: D102
56-
raise NotImplementedError
90+
from ansys.api.discovery.v1.commands.communication_pb2 import LogsRequest
91+
from ansys.api.discovery.v1.commonenums_pb2 import LogsPeriodType, LogsTarget
92+
93+
# Create the request - assumes all inputs are valid and of the proper type
94+
request = LogsRequest(
95+
target=LogsTarget.LOGSTARGET_CLIENT,
96+
period_type=(
97+
LogsPeriodType.LOGSPERIODTIME_CURRENT
98+
if not kwargs["all_logs"]
99+
else LogsPeriodType.LOGSPERIODTIME_ALL
100+
),
101+
null_path=None,
102+
null_period=None,
103+
)
104+
105+
# Call the gRPC service
106+
logs_generator = self.communication_stub.GetLogs(request)
107+
logs: dict[str, str] = {}
108+
109+
# Convert the response to a dictionary
110+
for chunk in logs_generator:
111+
if chunk.log_name not in logs:
112+
logs[chunk.log_name] = ""
113+
logs[chunk.log_name] += chunk.log_chunk.decode()
114+
115+
return {"logs": logs}
57116

58117
@protect_grpc
59118
def get_service_status(self, **kwargs) -> dict: # noqa: D102
60-
raise NotImplementedError
119+
from ansys.api.discovery.v1.commands.communication_pb2 import HealthRequest
120+
121+
# Create the request - assumes all inputs are valid and of the proper type
122+
request = HealthRequest()
123+
124+
# Call the gRPC service
125+
response = self.communication_stub.Health(request=request)
126+
127+
# Convert the response to a dictionary
128+
return {"healthy": True if response.message == "I am healthy!" else False}
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
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 assembly condition service implementation for v1."""
23+
24+
import grpc
25+
26+
from ansys.geometry.core.errors import protect_grpc
27+
28+
from ..base.assembly_condition import GRPCAssemblyConditionService
29+
from .conversions import build_grpc_id
30+
31+
32+
class GRPCAssemblyConditionServiceV1(GRPCAssemblyConditionService):
33+
"""Assembly condition service for gRPC communication with the Geometry server.
34+
35+
This class provides methods to interact with the Geometry server's
36+
assembly condition service. It is specifically designed for the v1 version of the
37+
Geometry API.
38+
39+
Parameters
40+
----------
41+
channel : grpc.Channel
42+
The gRPC channel to the server.
43+
"""
44+
45+
@protect_grpc
46+
def __init__(self, channel: grpc.Channel): # noqa: D102
47+
from ansys.api.discovery.v1.design.relationships.assemblycondition_pb2_grpc import (
48+
AssemblyConditionStub,
49+
)
50+
51+
self.stub = AssemblyConditionStub(channel)
52+
53+
@protect_grpc
54+
def create_align_condition(self, **kwargs) -> dict: # noqa: D102
55+
from ansys.api.discovery.v1.design.relationships.assemblycondition_pb2 import (
56+
CreateAlignRequest,
57+
CreateAlignRequestData,
58+
)
59+
60+
# Create the request - assumes all inputs are valid and of the proper type
61+
request = CreateAlignRequest(
62+
request_data=[
63+
CreateAlignRequestData(
64+
parent=build_grpc_id(kwargs["parent_id"]),
65+
geometric_a=build_grpc_id(kwargs["geometric_a_id"]),
66+
geometric_b=build_grpc_id(kwargs["geometric_b_id"]),
67+
)
68+
]
69+
)
70+
71+
# Call the gRPC service
72+
resp = self.stub.CreateAlign(request).response_data[0]
73+
74+
# Return the response - formatted as a dictionary
75+
return {
76+
"id": resp.align_condition.condition.id,
77+
"is_deleted": resp.align_condition.condition.is_deleted,
78+
"is_enabled": resp.align_condition.condition.is_enabled,
79+
"is_satisfied": resp.align_condition.condition.is_satisfied,
80+
"offset": resp.align_condition.offset,
81+
"is_reversed": resp.align_condition.is_reversed,
82+
"is_valid": resp.align_condition.is_valid,
83+
}
84+
85+
@protect_grpc
86+
def create_tangent_condition(self, **kwargs) -> dict: # noqa: D102
87+
from ansys.api.discovery.v1.design.relationships.assemblycondition_pb2 import (
88+
CreateTangentRequest,
89+
CreateTangentRequestData,
90+
)
91+
92+
# Create the request - assumes all inputs are valid and of the proper type
93+
request = CreateTangentRequest(
94+
request_data=[
95+
CreateTangentRequestData(
96+
parent=build_grpc_id(kwargs["parent_id"]),
97+
geometric_a=build_grpc_id(kwargs["geometric_a_id"]),
98+
geometric_b=build_grpc_id(kwargs["geometric_b_id"]),
99+
)
100+
]
101+
)
102+
103+
# Call the gRPC service
104+
resp = self.stub.CreateTangent(request).response_data[0]
105+
106+
# Return the response - formatted as a dictionary
107+
return {
108+
"id": resp.tangent_condition.condition.id,
109+
"is_deleted": resp.tangent_condition.condition.is_deleted,
110+
"is_enabled": resp.tangent_condition.condition.is_enabled,
111+
"is_satisfied": resp.tangent_condition.condition.is_satisfied,
112+
"offset": resp.tangent_condition.offset,
113+
"is_reversed": resp.tangent_condition.is_reversed,
114+
"is_valid": resp.tangent_condition.is_valid,
115+
}
116+
117+
@protect_grpc
118+
def create_orient_condition(self, **kwargs) -> dict: # noqa: D102
119+
from ansys.api.discovery.v1.design.relationships.assemblycondition_pb2 import (
120+
CreateOrientRequest,
121+
CreateOrientRequestData,
122+
)
123+
124+
# Create the request - assumes all inputs are valid and of the proper type
125+
request = CreateOrientRequest(
126+
request_data=[
127+
CreateOrientRequestData(
128+
parent=build_grpc_id(kwargs["parent_id"]),
129+
geometric_a=build_grpc_id(kwargs["geometric_a_id"]),
130+
geometric_b=build_grpc_id(kwargs["geometric_b_id"]),
131+
)
132+
]
133+
)
134+
135+
# Call the gRPC service
136+
resp = self.stub.CreateOrient(request).response_data[0]
137+
138+
# Return the response - formatted as a dictionary
139+
return {
140+
"id": resp.orient_condition.condition.id,
141+
"is_deleted": resp.orient_condition.condition.is_deleted,
142+
"is_enabled": resp.orient_condition.condition.is_enabled,
143+
"is_satisfied": resp.orient_condition.condition.is_satisfied,
144+
"offset": resp.orient_condition.offset,
145+
"is_reversed": resp.orient_condition.is_reversed,
146+
"is_valid": resp.orient_condition.is_valid,
147+
}

0 commit comments

Comments
 (0)