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. 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 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 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 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.