Product compatibility#
As PyAnsys libraries evolve, backward and forward compatibility issues can occur. Here are examples of two common issues:
An Ansys product has implemented certain features in its new server version that are not available in previous server versions. This causes backward incompatibility issues.
New server versions have suppressed support for certain operations after a a given version. This causes forward incompatibility issues.
Although there are different ways to handle these issues, some PyAnsys libraries, such as PyMAPDL and PyDPF-Core, handle them in the same way. To homogenize implementations in PyAnsys libraries, following their approach is recommended.
check_version.py
module approach#
A version checking module determines whether the Ansys product server you are connecting to provides support for certain operations. For an implementation example, see the check_version.py file for the DPF-Core library.
One of the easiest ways to keep track of the versions supported is to set up a
minimum version data structure in which forward compatibility is ensured.
Server versions earlier than the minimum version do not have access to this
functionality. The previously referenced check_version.py
file uses the
VERSIONS_MAP
structure.
Most Ansys products provide forward compatibility, meaning that features introduced in an earlier version are also supported in later versions. Suppressing a feature would lead to a backward compatibility issue.
Because the same type of issues can happen with the PyAnsys servers wrapping Ansys products, creating a similar maximum version data structure is is necessary. While there are no such implementations yet, it should work in the same way as the minimum version data structure.
version_requires
decorator#
The @version_requires
decorator applies version logic to
functionalities and methods available in the client. You can see how this
decorator is used in the check_version.py
file. Here is a generalized example:
class Client:
def __init__(self):
"""Connect to a fake server."""
self._server = FakeServer()
@version_requires((0, 1, 3)) # require 0.1.3
def meth_a(self):
"""Call method ``a`` on the server."""
return self._server.meth_a()
@version_requires((0, 2, 3)) # require 0.2.3
def meth_b(self):
"""Call method ``b`` on the server."""
return self._server.meth_b()
Whenever a client
object is created and a call is made to any of its methods,
such as meth_a()
, the decorator checks that the version is later than the one
specified in the decorator’s call. If it is not, a VersionError
is raised.
The self._server
member of the class is the server that the client is connected to. This
member is expected to have version information in its self._server._server_version
attribute. The decorator uses this version information to determine if the version is
higher than the threshold.
You can create a @max_version_supported
decorator to implement this same
kind of logic for forward incompatibility. Changing the @version_requires
decorator to @min_version_required
is recommended.