Skip to content

Commit 4d019b7

Browse files
authored
Merge pull request #9 from pyansys/fix/info_on_empty
use message from fc
2 parents e9744f9 + 94b3f64 commit 4d019b7

File tree

7 files changed

+108
-90
lines changed

7 files changed

+108
-90
lines changed

.ci/azure-pipelines.yml

+7-4
Original file line numberDiff line numberDiff line change
@@ -65,25 +65,28 @@ jobs:
6565
feedsToUse: 'internal'
6666
vstsFeed: '705e121a-9631-49f5-8aaf-c7142856f923'
6767
vstsFeedPackage: 'f913c1d3-1fe4-404c-8c28-15a234e56803'
68-
vstsPackageVersion: '21.1.3'
68+
vstsPackageVersion: '21.1.4'
6969

7070
- script: |
7171
@echo on
7272
dir $(System.DefaultWorkingDirectory)
7373
set THISDIR=$(System.DefaultWorkingDirectory)
7474
set PATH=%THISDIR%\server\v211\tp\IntelMKL\2020.0.166\winx64\;%THISDIR%\server\v211\tp\hdf5\1.8.14\winx64\;%THISDIR%\server\v211\tp\CFFSDK\lib\winx64;%THISDIR%\res_files\;%PATH%
7575
cd %THISDIR%\server\v211\aisol\bin\winx64
76-
START /B Ans.Dpf.Grpc.exe --address 127.0.0.1 --port %DPF_PORT%
76+
START /B Ans.Dpf.Grpc.exe --address 127.0.0.1 --port %DPF_PORT% > log.txt 2>&1
7777
python -c "from ansys.dpf import core; core.connect_to_server(port=$(DPF_PORT)); print('Python Connected')"
7878
displayName: Start DPF Server
7979
8080
- script: |
8181
pip install -r requirements_test.txt
8282
cd tests
83-
pytest -v --junitxml=junit/test-results.xml --cov ansys.dpf.core --cov-report=xml --ignore=test_field.py
84-
pytest -v test_field.py
83+
pytest -v --junitxml=junit/test-results.xml --cov ansys.dpf.core --cov-report=xml
8584
displayName: Test Core API
8685
86+
- script: |
87+
type $(System.DefaultWorkingDirectory)\server\v211\aisol\bin\winx64\log.txt
88+
displayName: 'Show DPF Server Logs'
89+
condition: always()
8790
8891
- job: Linux
8992
variables:

ansys/dpf/core/collection.py

+33-32
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
from ansys.dpf.core.scoping import Scoping, scoping_pb2
88
from ansys.dpf.core.field import Field, field_pb2
99
from ansys.dpf.core.time_freq_support import TimeFreqSupport
10+
from ansys.dpf.core.errors import protect_grpc
11+
1012

1113
class Collection:
1214
"""A class used to represent a Collection which contains
@@ -18,19 +20,19 @@ class Collection:
1820
Create a collection from a Collection message.
1921
2022
channel : channel, optional
21-
Channel connected to the remote or local instance. Defaults to the global channel.
23+
Channel connected to the remote or local instance. When
24+
``None``, attempts to use the the global channel.
2225
2326
"""
2427

25-
def __init__(self,dpf_type, collection=None, channel=None):
26-
28+
def __init__(self, dpf_type, collection=None, channel=None):
2729
if channel is None:
2830
channel = dpf.core._global_channel()
2931

3032
self._channel = channel
3133
self._stub = self._connect()
3234
self._type = dpf_type
33-
35+
3436
if collection is None:
3537
request = collection_pb2.CollectionRequest()
3638
if hasattr(dpf_type, 'name'):
@@ -39,6 +41,8 @@ def __init__(self,dpf_type, collection=None, channel=None):
3941
stype = dpf_type
4042
request.type = base_pb2.Type.Value(stype.upper())
4143
self._message = self._stub.Create(request)
44+
elif hasattr(collection, '_message'):
45+
self._message = collection._message
4246
else:
4347
self._message = collection
4448

@@ -52,14 +56,14 @@ def set_labels(self, labels):
5256
['time','complex']
5357
5458
"""
55-
if len(self.__info__()['labels'])!=0:
56-
print("the collection has already labels :",self.__info__()['labels'],'deleting existing abels is not implemented yet')
59+
if len(self._info['labels'])!=0:
60+
print("the collection has already labels :",self._info['labels'],'deleting existing abels is not implemented yet')
5761
return
5862
request = collection_pb2.UpdateLabelsRequest()
5963
request.collection.CopyFrom(self._message)
6064
request.labels.labels.extend(labels)
6165
self._stub.UpdateLabels(request)
62-
66+
6367
def add_label(self, label):
6468
"""add the requested label to scope the collection
6569
@@ -70,12 +74,11 @@ def add_label(self, label):
7074
'time'
7175
7276
"""
73-
7477
request = collection_pb2.UpdateLabelsRequest()
7578
request.collection.CopyFrom(self._message)
7679
request.labels.labels.extend([label])
7780
self._stub.UpdateLabels(request)
78-
81+
7982
def _get_labels(self):
8083
"""get the labels scoping the collection
8184
@@ -86,10 +89,10 @@ def _get_labels(self):
8689
['time','complex']
8790
8891
"""
89-
return self.__info__()['labels']
90-
92+
return self._info['labels']
93+
9194
labels = property(_get_labels, set_labels, "labels")
92-
95+
9396
def _get_entries(self, label_space_or_index):
9497
"""Returns the entry at a requested index or label space
9598
@@ -162,10 +165,11 @@ def get_label_space(self, index):
162165
dictOut[key]=out[key]
163166

164167
return dictOut
165-
168+
166169
def get_ids(self, label="time"):
167-
168-
"""
170+
"""Get the IDs corresponding to the input label.
171+
172+
169173
Parameters
170174
----------
171175
label : str
@@ -176,13 +180,13 @@ def get_ids(self, label="time"):
176180
ids : list of int
177181
ids corresponding to the input label
178182
"""
179-
ids =[]
180-
for i in range(0,self.__len__()):
181-
current_scop =self.get_label_space(i)
182-
if label in current_scop and current_scop[label] not in ids:
183+
ids = []
184+
for i in range(len(self)):
185+
current_scop = self.get_label_space(i)
186+
if label in current_scop and current_scop[label] not in ids:
183187
ids.append(current_scop[label])
184188
return ids
185-
189+
186190
def __getitem__(self, key):
187191
"""Returns the entry at a requested index
188192
@@ -222,7 +226,7 @@ def _add_entry(self, label_space, entry):
222226
for key in label_space:
223227
request.label_space.label_space[key] = label_space[key]
224228
self._stub.UpdateEntry(request)
225-
229+
226230
def _get_time_freq_support(self):
227231
"""
228232
Returns
@@ -235,19 +239,20 @@ def _get_time_freq_support(self):
235239
message = self._stub.GetSupport(request)
236240
return TimeFreqSupport(time_freq_support=message)
237241

238-
239242
def _connect(self):
240243
"""Connect to the grpc service"""
241244
return collection_pb2_grpc.CollectionServiceStub(self._channel)
242245

243-
def __info__(self):
244-
list = self._stub.List(self._message)
245-
out = {"len":list.count_entries, "labels":list.labels.labels}
246-
return out
247-
246+
@property
247+
@protect_grpc
248+
def _info(self):
249+
"""Length and labels of this container"""
250+
list_stub = self._stub.List(self._message)
251+
return {"len": list_stub.count_entries, "labels": list_stub.labels.labels}
252+
248253
def __len__(self):
249254
"""Return number of entries"""
250-
return self.__info__()["len"]
255+
return self._info["len"]
251256

252257
def __del__(self):
253258
try:
@@ -258,7 +263,3 @@ def __del__(self):
258263
def __iter__(self):
259264
for i in range(len(self)):
260265
yield self[i]
261-
262-
263-
# -*- coding: utf-8 -*-
264-

ansys/dpf/core/common.py

+15-18
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,32 @@
66

77
from ansys.grpc.dpf import base_pb2 as base_pb2
88

9+
910
def camel_to_snake_case(name):
1011
return re.sub(r'(?<!^)(?=[A-Z])', '_', name).lower()
1112

13+
1214
def remove_spaces(name):
1315
out = name.lower()
14-
out = out.replace(" ", "_")
15-
out = out.replace("-", "_")
16+
out = out.replace(" ", "_")
17+
out = out.replace("-", "_")
1618
return out
1719

20+
1821
def snake_to_camel_case(name):
1922
return ''.join(word.title() for word in name.split('_'))
2023

24+
2125
class smart_dict_camel(dict):
2226
def __missing__(self, key):
2327
return camel_to_snake_case(key)
24-
28+
29+
2530
class smart_dict_unit_system(dict):
2631
def __missing__(self, key):
2732
return 'unknown'
2833

34+
2935
names = [m.lower() for m in base_pb2.Type.keys()]
3036
names.append("fields_container")
3137
types = Enum('types', names)
@@ -49,10 +55,10 @@ class locations:
4955

5056
# one per time step
5157
time_freq = "TimeFreq_sets"
52-
58+
5359
#applies everywhere
54-
overall="overall"
55-
60+
overall = "overall"
61+
5662

5763

5864
def field_from_array(arr):
@@ -92,17 +98,8 @@ def field_from_array(arr):
9298
else:
9399
raise shp_err
94100

95-
# TODO: speedup, very inefficient
96-
nentities = arr.shape[0]
97-
ids=[]
98-
field = Field(nentities=nentities, nature=nature)
101+
n_entities = arr.shape[0]
102+
field = Field(nentities=n_entities, nature=nature)
99103
field.data = arr
100-
101-
for i in range(nentities):
102-
ids.append(i+1)
103-
104-
field.scoping.ids =ids
105-
104+
field.scoping.ids = np.arange(1, n_entities + 1)
106105
return field
107-
108-

ansys/dpf/core/errors.py

+13-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
from grpc._channel import _InactiveRpcError, _MultiThreadedRendezvous
22

33

4-
class DPFServerError(RuntimeError):
4+
class DPFServerException(Exception):
55
"""Raised when the DPF Server has encountered an error"""
66

77
def __init__(self, msg=''):
8-
RuntimeError.__init__(self, msg)
8+
Exception.__init__(self, msg)
9+
10+
11+
class DPFServerNullObject(Exception):
12+
"""Raised when the DPF Server has encountered an error"""
13+
14+
def __init__(self, msg=''):
15+
Exception.__init__(self, msg)
916

1017

1118
class InvalidPortError(OSError):
@@ -25,7 +32,10 @@ def wrapper(*args, **kwargs):
2532
try:
2633
out = func(*args, **kwargs)
2734
except (_InactiveRpcError, _MultiThreadedRendezvous) as error:
28-
raise DPFServerError(error.details()) from None
35+
details = error.details()
36+
if 'object is null in the dataBase' in details:
37+
raise DPFServerNullObject(details) from None
38+
raise DPFServerException(details) from None
2939

3040
return out
3141

ansys/dpf/core/fields_container.py

+13-11
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from ansys.dpf.core.collection import Collection
44
from ansys.dpf.core.common import types
55

6+
67
class FieldsContainer(Collection):
78
"""A class used to represent a FieldsContainer which contains
89
fields belonging to an analysis.
@@ -11,28 +12,29 @@ class FieldsContainer(Collection):
1112
----------
1213
fields_container : ansys.grpc.dpf.fields_container_pb2.FieldsContainer, optional
1314
Create a fields container from a FieldsContainer message.
14-
15+
1516
channel : channel, optional
16-
Channel connected to the remote or local instance. Defaults to the global channel.
17-
17+
Channel connected to the remote or local instance. When
18+
``None``, attempts to use the the global channel.
19+
1820
"""
1921

2022
def __init__(self, fields_container=None, channel=None):
2123
"""Intialize the scoping with either optional scoping message,
2224
or by connecting to a stub.
2325
"""
2426
if channel is None:
25-
channel = dpf.core._global_channel()
26-
self._channel=channel
27+
channel = dpf.core._global_channel()
28+
self._channel = channel
2729
self._stub = self._connect()
28-
29-
30+
3031
self._component_index = None # component index
3132
self._component_info = None # for norm/max/min
32-
33-
Collection.__init__(self,types.field, collection=fields_container, channel= channel)
34-
35-
def get_fields_by_time_complex_ids(self,timeid=None, complexid=None):
33+
34+
Collection.__init__(self, types.field,
35+
collection=fields_container, channel=channel)
36+
37+
def get_fields_by_time_complex_ids(self, timeid=None, complexid=None):
3638
"""Returns the fields at a requested index or scoping
3739
3840
Parameters

tests/test_field.py

+8-12
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
from ansys import dpf
66

7-
# true when running on Azure Virtual enviornment on windows
8-
ON_AZURE = False
9-
if os.name == 'nt':
10-
ON_AZURE = os.environ.get('ON_AZURE', '').lower() == 'true'
7+
# # true when running on Azure Virtual enviornment on windows
8+
# ON_WINDOWS_AZURE = False
9+
# if os.name == 'nt':
10+
# ON_WINDOWS_AZURE = os.environ.get('ON_AZURE', '').lower() == 'true'
1111

1212

1313
def test_create_field():
@@ -172,11 +172,11 @@ def test_resize_field():
172172
assert field.elementary_data_count == 20
173173
assert field.size == 20
174174

175-
175+
176176
def test_fromarray_field():
177-
data = np.empty((100,6))
177+
data = np.empty((100, 6))
178178
f = dpf.core.field_from_array(data)
179-
assert f.shape ==(100,6)
179+
assert f.shape == (100, 6)
180180

181181

182182
def test_field_definition_field(allkindofcomplexity):
@@ -240,13 +240,9 @@ def test_mesh_support_field(allkindofcomplexity):
240240
assert len(mesh.elements.scoping) == 10292
241241

242242

243-
@pytest.mark.skip(ON_AZURE, reason='Seems to cause segfault on Azure')
243+
# @pytest.mark.skipif(ON_WINDOWS_AZURE, reason='Causes segfault on Azure')
244244
def test_delete_auto_field():
245245
field = dpf.core.Field()
246246
field2 = dpf.core.Field(field=field)
247247
del field
248248
assert field2.location == 'Nodal'
249-
250-
251-
if __name__ == '__main__':
252-
test_create_field()

0 commit comments

Comments
 (0)