11"""Provides the wrapper for a Comsol client instance."""
22
3+ from __future__ import annotations
4+
35from . import discovery
46from .model import Model
57from .config import option
1113from pathlib import Path
1214from logging import getLogger
1315
16+ from typing import overload , Iterator
17+ from jpype import JClass
1418
15- log = getLogger (__package__ )
1619
1720# The following look-up table is used by the `modules()` method. It is
1821# based on the table on page 41 of Comsol 6.0's Programming Reference
7275 'WAVEOPTICS' : 'Wave Optics' ,
7376}
7477
78+ log = getLogger (__package__ )
79+
7580
7681class Client :
7782 """
@@ -121,11 +126,31 @@ class Client:
121126 /com/comsol/model/util/ModelUtil.html
122127 """
123128
129+ version : str
130+ """Comsol version (e.g., `'6.0'`) the client is running on."""
131+
132+ standalone : bool
133+ """Whether this is a stand-alone client or connected to a server."""
134+
135+ port : int | None
136+ """Port number on which the client has connected to the server."""
137+
138+ host : str | None
139+ """Host name or IP address of the server the client is connected to."""
140+
141+ java : JClass
142+ """Java model object that this class instance is wrapped around."""
143+
124144 ############
125145 # Internal #
126146 ############
127147
128- def __init__ (self , cores = None , version = None , port = None , host = 'localhost' ):
148+ def __init__ (self ,
149+ cores : int = None ,
150+ version : str = None ,
151+ port : int = None ,
152+ host : str = 'localhost' ,
153+ ):
129154
130155 # Make sure this is the one and only client.
131156 if jpype .isJVMStarted ():
@@ -206,27 +231,18 @@ def __init__(self, cores=None, version=None, port=None, host='localhost'):
206231 # Log that we're done so the start-up time may be inspected.
207232 log .info ('Stand-alone client initialized.' )
208233
209- # Save and document instance attributes.
210- # It seems to be necessary to document the instance attributes here
211- # towards the end of the method. If done earlier, Sphinx would not
212- # render them in source-code order, even though that's what we
213- # request in the configuration. This might be a bug in Sphinx.
214- self .version = backend ['name' ]
215- """Comsol version (e.g., `'6.0'`) the client is running on."""
234+ # Save instance attributes.
235+ self .version = backend ['name' ]
216236 self .standalone = standalone
217- """Whether this is a stand-alone client or connected to a server."""
218- self .port = None
219- """Port number on which the client has connected to the server."""
220- self .host = None
221- """Host name or IP address of the server the client is connected to."""
222- self .java = java
223- """Java model object that this class instance is wrapped around."""
237+ self .port = None
238+ self .host = None
239+ self .java = java
224240
225241 # Try to connect to server if not a stand-alone client.
226- if not standalone and host :
242+ if not standalone and host and port is not None :
227243 self .connect (port , host )
228244
229- def __repr__ (self ):
245+ def __repr__ (self ) -> str :
230246 if self .standalone :
231247 connection = 'stand-alone'
232248 elif self .port :
@@ -235,17 +251,17 @@ def __repr__(self):
235251 connection = 'disconnected'
236252 return f'{ self .__class__ .__name__ } ({ connection } )'
237253
238- def __contains__ (self , item ) :
254+ def __contains__ (self , item : str | Model ) -> bool :
239255 if isinstance (item , str ) and item in self .names ():
240256 return True
241257 if isinstance (item , Model ) and item in self .models ():
242258 return True
243259 return False
244260
245- def __iter__ (self ):
261+ def __iter__ (self ) -> Iterator [ Model ] :
246262 yield from self .models ()
247263
248- def __truediv__ (self , name ) :
264+ def __truediv__ (self , name : str ) -> Model :
249265 if isinstance (name , str ):
250266 for model in self :
251267 if name == model .name ():
@@ -262,25 +278,25 @@ def __truediv__(self, name):
262278 ##############
263279
264280 @property
265- def cores (self ):
281+ def cores (self ) -> int :
266282 """Number of processor cores (threads) the Comsol session is using."""
267283 cores = self .java .getPreference ('cluster.processor.numberofprocessors' )
268284 cores = int (str (cores ))
269285 return cores
270286
271- def models (self ):
287+ def models (self ) -> list [ Model ] :
272288 """Returns all models currently held in memory."""
273289 return [Model (self .java .model (tag )) for tag in self .java .tags ()]
274290
275- def names (self ):
291+ def names (self ) -> list [ str ] :
276292 """Returns the names of all loaded models."""
277293 return [model .name () for model in self .models ()]
278294
279- def files (self ):
295+ def files (self ) -> list [ Path ] :
280296 """Returns the file-system paths of all loaded models."""
281297 return [model .file () for model in self .models ()]
282298
283- def modules (self ):
299+ def modules (self ) -> list [ str ] :
284300 """Returns the names of available licensed modules/products."""
285301 names = []
286302 for (key , value ) in modules .items ():
@@ -295,7 +311,7 @@ def modules(self):
295311 # Interaction #
296312 ###############
297313
298- def load (self , file ) :
314+ def load (self , file : Path | str ) -> Model :
299315 """Loads a model from the given `file` and returns it."""
300316 file = Path (file ).resolve ()
301317 if self .caching () and file in self .files ():
@@ -307,6 +323,10 @@ def load(self, file):
307323 log .info ('Finished loading model.' )
308324 return model
309325
326+ @overload
327+ def caching (self , state : None ) -> bool : ...
328+ @overload
329+ def caching (self , state : bool ): ...
310330 def caching (self , state = None ):
311331 """
312332 Enables or disables caching of previously loaded models.
@@ -329,7 +349,7 @@ def caching(self, state=None):
329349 log .error (error )
330350 raise ValueError (error )
331351
332- def create (self , name = None ):
352+ def create (self , name : str = None ) -> Model :
333353 """
334354 Creates a new model and returns it as a [`Model`](#Model) instance.
335355
@@ -345,7 +365,7 @@ def create(self, name=None):
345365 log .debug (f'Created model "{ name } " with tag "{ java .tag ()} ".' )
346366 return model
347367
348- def remove (self , model ):
368+ def remove (self , model : str | Model ):
349369 """Removes the given [`model`](#Model) from memory."""
350370 if isinstance (model , str ):
351371 if model not in self .names ():
@@ -382,7 +402,7 @@ def clear(self):
382402 # Remote #
383403 ##########
384404
385- def connect (self , port , host = 'localhost' ):
405+ def connect (self , port : int , host : str = 'localhost' ):
386406 """
387407 Connects the client to a server.
388408
0 commit comments