3131import numpy as np
3232import pandas as pd
3333
34+ import odbclient
35+
3436
3537class OdbServerError (Exception ):
3638 """Raised when the ODB Server launch fails."""
@@ -148,7 +150,13 @@ def __init__(self, odb_file, abaqus_bin=None, python_env_path=None):
148150 if lock_file_exists :
149151 self ._gulp_lock_file_warning ()
150152
151- self ._wait_for_server_ready_sign ()
153+ server_version , server_python_version = self ._wait_for_server_ready_sign ()
154+ _raise_if_version_mismatch (server_version )
155+ if server_python_version == "2" :
156+ self ._parse_response = self ._parse_response_py2
157+ else :
158+ self ._parse_response = self ._parse_response_py3
159+
152160
153161 def _gulp_lock_file_warning (self ):
154162 self ._proc .stdout .readline ()
@@ -158,6 +166,8 @@ def _wait_for_server_ready_sign(self):
158166 def wait_for_input (stdout , queue ):
159167 sign = stdout .read (5 )
160168 queue .put (sign )
169+ version_sign = stdout .readline ()
170+ queue .put (version_sign )
161171
162172 queue = QU .Queue ()
163173 thread = THR .Thread (target = wait_for_input , args = (self ._proc .stdout , queue ))
@@ -173,6 +183,12 @@ def wait_for_input(stdout, queue):
173183 else :
174184 if sign != b'ready' :
175185 raise OdbServerError ("Expected ready sign from server, received %s" % sign )
186+
187+ try :
188+ sign = queue .get_nowait ()
189+ return _ascii (_decode , sign ).strip ().split ()
190+ except QU .Empty :
191+ return "unannounced" , "2"
176192 return
177193
178194 def instance_names (self ):
@@ -203,8 +219,11 @@ def node_coordinates(self, instance_name, nset_name=''):
203219 """
204220 self ._fail_if_instance_invalid (instance_name )
205221 index , node_data = self ._query ('get_nodes' , (instance_name , nset_name ))
206- return pd .DataFrame (data = node_data , columns = ['x' , 'y' , 'z' ],
207- index = pd .Index (index , name = 'node_id' , dtype = np .int64 ))
222+ return pd .DataFrame (
223+ data = node_data ,
224+ columns = ['x' , 'y' , 'z' ],
225+ index = pd .Index (index , name = 'node_id' , dtype = np .int64 ),
226+ )
208227
209228 def element_connectivity (self , instance_name , elset_name = '' ):
210229 """Query the element connectivity of an instance.
@@ -447,6 +466,7 @@ def history_region_description(self, step_name, history_region_name):
447466 """Query the description of a history Regions of a given step.
448467
449468 Parameters
469+
450470 ----------
451471 step_name : string
452472 The name of the step
@@ -491,11 +511,21 @@ def _send_command(self, command, args=None):
491511 pickle .dump ((command , args ), self ._proc .stdin , protocol = 2 )
492512 self ._proc .stdin .flush ()
493513
494- def _parse_response (self ):
495- expected_size , = struct .unpack ("Q" , self ._proc .stdout .read (8 ))
496- pickle_data = self ._proc .stdout .read (expected_size )
514+ def _parse_response_py2 (self ):
515+ pickle_data = b''
516+ while True :
517+ line = self ._proc .stdout .readline ().rstrip () + b'\n '
518+ pickle_data += line
519+ if line == b'.\n ' :
520+ break
497521 return pickle .loads (pickle_data , encoding = 'bytes' )
498522
523+ def _parse_response_py3 (self ):
524+ msg = self ._proc .stdout .read (8 )
525+ expected_size , = struct .unpack ("Q" , msg )
526+ pickle_data = self ._proc .stdout .read (expected_size )
527+ return pickle .loads (pickle_data )
528+
499529 def __del__ (self ):
500530 if self ._proc is not None :
501531 self ._send_command ('QUIT' )
@@ -536,6 +566,7 @@ def _decode(arg):
536566 return [_decode (element ) for element in arg ]
537567 return arg
538568
569+
539570def _guess_abaqus_bin ():
540571 if sys .platform == 'win32' :
541572 return _guess_abaqus_bin_windows ()
@@ -582,9 +613,25 @@ def _determine_server_python_version(abaqus_bin):
582613 return version_string [:version_string .rfind ("." )]
583614
584615
585-
586616def _guess_python_env_path (python_env_path ):
587617 cand = python_env_path or os .path .join (os .environ ['HOME' ], '.conda' , 'envs' , 'odbserver' )
588618 if os .path .exists (cand ):
589619 return cand
590620 return None
621+
622+
623+ def _raise_if_version_mismatch (server_version ):
624+ def strip_version (version ):
625+ pos = version .find (".post" )
626+ if pos == - 1 :
627+ return version
628+ return version [:pos ]
629+
630+ server_version = strip_version (server_version )
631+ client_version = strip_version (odbclient .__version__ )
632+
633+ if client_version != server_version :
634+ raise RuntimeError (
635+ "Version mismatch: "
636+ f"odbserver version { server_version } != odbclient version { client_version } "
637+ )
0 commit comments