Skip to content

Commit

Permalink
Merge branch 'main' into fix/save_designs_as
Browse files Browse the repository at this point in the history
  • Loading branch information
ekrja authored Sep 30, 2024
2 parents a2867ee + 79c4d12 commit bd0cb14
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 2 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ tests = [
"matplotlib>=3.5.3",
]
doc = [
"ansys-sphinx-theme==1.0.8",
"ansys-sphinx-theme==1.0.11",
"matplotlib==3.9.2",
"numpydoc==1.7.0",
"pypandoc==1.13",
Expand Down
7 changes: 7 additions & 0 deletions src/ansys/optislang/core/osl_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
from abc import ABC, abstractmethod
from typing import NamedTuple, Optional

from ansys.optislang.core import utils


class OslVersion(NamedTuple):
"""optiSLang version.
Expand Down Expand Up @@ -55,6 +57,11 @@ def __init__(self): # pragma: no cover
"""``OslServer`` class is an abstract base class and cannot be instantiated."""
pass

@property
def is_remote(self) -> bool:
"""Determines whether the optiSLang server does not run on localhost."""
return self.host is not None and self.port is not None and not utils.is_localhost(self.host)

@property
@abstractmethod
def host(self) -> Optional[str]: # pragma no cover
Expand Down
10 changes: 10 additions & 0 deletions src/ansys/optislang/core/tcp/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2140,6 +2140,9 @@ def get_inner_output_slots(
def get_omdb_files(self) -> Tuple[File]:
"""Get paths to omdb files.
This method is supported only when the client runs on the same file
system as the server, i.e., the server is not remote.
Returns
-------
Tuple[File]
Expand All @@ -2153,7 +2156,14 @@ def get_omdb_files(self) -> Tuple[File]:
Raised when a command or query fails.
TimeoutError
Raised when the timeout float value expires.
RuntimeError
Raised when the server is remote.
"""
if self._osl_server.is_remote:
raise RuntimeError(
"Paths to omdb files cannot be provided when connected to the remote server."
)

statuses_info = self._get_status_info()
wdirs = [Path(status_info["working dir"]) for status_info in statuses_info]
omdb_files = []
Expand Down
3 changes: 2 additions & 1 deletion src/ansys/optislang/core/tcp/osl_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

from deprecated.sphinx import deprecated

from ansys.optislang.core import utils
from ansys.optislang.core.encoding import force_bytes, force_text
from ansys.optislang.core.errors import (
ConnectionEstablishedError,
Expand Down Expand Up @@ -799,7 +800,7 @@ def timeout(self, timeout) -> None:
@property
def host_addresses(self) -> List[str]:
"""Local IP addresses associated with self.__listener_socket."""
addresses = [i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]
addresses = utils.get_localhost_addresses()
# Explicitly add localhost to workaround potential networking issues
addresses.append("127.0.0.1")
return addresses
Expand Down
42 changes: 42 additions & 0 deletions src/ansys/optislang/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@

import collections
from enum import Enum
import ipaddress
import os
from pathlib import Path
import re
import socket
import sys
from typing import (
DefaultDict,
Expand Down Expand Up @@ -454,3 +456,43 @@ def iter_awp_roots() -> Iterator[Tuple[int, Path]]:
def is_iron_python():
"""Whether current platform is IronPython."""
return sys.platform == "cli"


def get_localhost_addresses() -> List[str]:
"""Get addresses of the localhost machine.
Returns
-------
List[str]
List of addresses of the localhost machine.
"""
return [i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]


def is_localhost(host: str) -> bool:
"""Determine whether the host is localhost.
Parameters
----------
host : str
IPv4/v6 address or domain name of the host.
Returns
-------
bool
``True`` if the provided ``host`` is localhost; ``False`` otherwise.
"""
try:
addrinfo = socket.getaddrinfo(host=host, port=None)
except socket.gaierror:
return False

localhost_addresses = get_localhost_addresses()
for _, _, _, _, sockaddr in addrinfo:
try:
ip = sockaddr[0]
if not ipaddress.ip_address(ip).is_loopback and ip not in localhost_addresses:
return False
except ValueError:
return False
return True
2 changes: 2 additions & 0 deletions tests/tcp/test_tcp_osl_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,8 @@ def test_tcp_osl_properties(osl_server_process: OslServerProcess):
tcp_osl_server.timeout = 20
assert tcp_osl_server.timeout == 20

assert not tcp_osl_server.is_remote

with pytest.raises(ValueError):
tcp_osl_server.timeout = -5
with pytest.raises(ValueError):
Expand Down
40 changes: 40 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,28 @@
# SOFTWARE.

from enum import Enum
from socket import getaddrinfo, gethostname

import pytest

from ansys.optislang.core import utils


@pytest.fixture
def localhost_addresses():
"""Get addresses of the local machine excluding loopback addresses."""
addresses = []
for _, _, _, _, sockaddr in getaddrinfo(gethostname(), None):
addresses.append(sockaddr[0])
return addresses


@pytest.fixture
def loopback_addresses():
"""Get loopback addresses."""
return ["127.0.0.0", "127.0.0.1", "127.255.255.255", "::1", "localhost"]


def test_enum_from_str():
class MyEnum(Enum):
ONE = 0
Expand All @@ -42,3 +58,27 @@ class MyEnum(Enum):
assert utils.enum_from_str("one", MyEnum) == MyEnum.ONE
assert utils.enum_from_str("ONE", MyEnum) == MyEnum.ONE
assert utils.enum_from_str("ONX", MyEnum, ["X", "E"]) == MyEnum.ONE


def test_get_localhost_addresses(localhost_addresses):
for address in utils.get_localhost_addresses():
assert address in localhost_addresses


def test_is_localhost(loopback_addresses, localhost_addresses):
random_addresses = [
"192.168.101.1",
"10.0.10.1",
"130.10.20.1",
"2001:0db8:85a3:0000:0000:8a2e:0370:7334",
"fe80::1ff:fe23:4567:890a%3",
]

for loopback_address in loopback_addresses:
assert utils.is_localhost(loopback_address) == True

for localhost_address in localhost_addresses:
assert utils.is_localhost(localhost_address) == True

for random_address in random_addresses:
assert utils.is_localhost(random_address) == (random_address in localhost_address)

0 comments on commit bd0cb14

Please sign in to comment.