Skip to content

Commit

Permalink
Merge pull request #34 from SweepMe/device_communication-redesign
Browse files Browse the repository at this point in the history
Device communication redesign
  • Loading branch information
fk3 authored Feb 1, 2024
2 parents ada2b1e + 18eb79c commit c536686
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/pysweepme/Architecture.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def extract_information(self):
"any",
f"any-{self._python_bitness_str}",
f"{self._python_version_str}-any",
f"{self._python_version_str}-{self._python_bitness_str}"
f"{self._python_version_str}-{self._python_bitness_str}",
]
self._information_extracted = True

Expand Down
61 changes: 45 additions & 16 deletions src/pysweepme/EmptyDeviceClass.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import os
from configparser import ConfigParser
from copy import deepcopy
from typing import TYPE_CHECKING, Any
from typing import TYPE_CHECKING, Any, ClassVar

from pysweepme.UserInterface import message_balloon, message_box, message_info, message_log

Expand All @@ -42,10 +42,10 @@ class EmptyDevice:
str
] = [] # static variable that can be used in a driver to define a list of function names that can be used as action

def __init__(self) -> None:
# here to make sure that it is known, later it is overwritten by SweepMe!
self.device_communication: dict[str, Any] = {}
_device_communication: ClassVar[dict[str, Any]] = {}
_parameter_store: ClassVar[dict[str, Any]] = {}

def __init__(self) -> None:
self.variables: list[str] = []
self.units: list[str] = []
self.plottype: list[bool] = [] # True if plotted
Expand Down Expand Up @@ -75,11 +75,24 @@ def __init__(self) -> None:

self._latest_parameters: dict[str, Any] | None = None

# ParameterStore
# needs to be defined here in case the device class is used standalone with pysweepme
# Otherwise, the object is handed over by the module during create_Device
# The ParameterStore can then be used to store and restore some parameters after re-instantiating.
self._ParameterStore: dict[Any, Any] = {}
@property
def device_communication(self) -> dict[str, Any]:
"""Single (global) dictionary where drivers can store their information that can be shared across instances."""
return EmptyDevice._device_communication

@device_communication.setter
def device_communication(self, _: object) -> None:
msg = (
"Changing the device_communication dictionary is not allowed.\n"
"Please only work on specific indices, e.g. \n"
">>> self.device_communication[<your index>] = <your value>"
)
raise TypeError(msg)

@staticmethod
def clear_device_communication() -> None:
"""Clear all information that have been stored in the device_communication dictionary."""
EmptyDevice._device_communication = {}

def list_functions(self):
"""Returns a list of all function names that are individually defined by the driver, e.g. get/set functions.
Expand All @@ -91,14 +104,30 @@ def list_functions(self):

return list(set(all_functions) - set(empty_device_functions))

def store_parameter(self, key, value):
"""Stores a value in the ParameterStore for a given key."""
self._ParameterStore[key] = value
def store_parameter(self, key: str, value: object) -> None:
"""Stores a value in the ParameterStore for a given key.
Drivers can use the ParameterStore to store information and restore the same information later even in
a new instance.
Args:
key: The key under which the information is stored. It should be unique and not conflicting with
other drivers.
value: The information to be stored.
"""
self._parameter_store[key] = value

def restore_parameter(self, key):
"""Restores a parameter from the ParameterStore for a given key."""
if key in self._ParameterStore:
return self._ParameterStore[key]
def restore_parameter(self, key: str) -> Any: # noqa: ANN401 # The type of the information is up to the user
"""Restores a parameter from the ParameterStore for a given key.
Args:
key: The key under which the information was stored before.
Returns:
The stored information, or None if no information can be found under the given key.
"""
if key in self._parameter_store:
return self._parameter_store[key]
return None

def _on_run(self):
Expand Down
2 changes: 1 addition & 1 deletion src/pysweepme/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
# SOFTWARE.


__version__ = "1.5.6.7"
__version__ = "1.5.6.8"

import sys

Expand Down
2 changes: 1 addition & 1 deletion src/pysweepme/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def _is_version_reached(version: str) -> bool:
version_tuple = tuple(map(int, version.split(".")))
# zip and un-zip the version tuples to make them same length
version_tuple, compare = zip(*zip_longest(version_tuple, _pysweepme_version, fillvalue=0))
if version_tuple < compare:
if version_tuple > compare:
return False
return True

Expand Down
3 changes: 3 additions & 0 deletions src/pysweepme/pysweepme_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

class FileIOContextProtocol(Protocol):
"""Protocol for a ContextManager for IO Operations."""

def __enter__(self) -> IO[Any]:
"""Function to return a file descriptor."""

Expand All @@ -48,6 +49,7 @@ class FileIOProtocolWithoutModifiedCheck(Protocol):
In contrast to Path's open(), this function does not return a file descriptor directly and instead always
must be used in conjunction with a `with` statement that will return the file descriptor of the opened file.
"""

def open( # noqa: A003, PLR0913
self,
mode: str = "r",
Expand All @@ -65,6 +67,7 @@ class FileIOProtocolWithModifiedCheck(FileIOProtocolWithoutModifiedCheck):
In contrast to Path's open(), this function does not return a file descriptor directly and instead always
must be used in conjunction with a `with` statement that will return the file descriptor of the opened file.
"""

def set_full_read(self) -> None:
"""Function that shall be called when a file is read completely.
Expand Down
12 changes: 6 additions & 6 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ def test_tuple_extract(self) -> None:
def test_version_compare(self) -> None:
"""Test that version strings are compared semantically."""
with patch("pysweepme._utils._pysweepme_version", new_callable=PropertyMock(return_value=(1, 2, 3, 4))):
assert _is_version_reached("1.2") is False
assert _is_version_reached("1.2.3.3.99") is False

assert _is_version_reached("1.3") is True
assert _is_version_reached("1.2") is True
assert _is_version_reached("1.2.3.3.99") is True
assert _is_version_reached("1.2.3.4") is True
assert _is_version_reached("1.2.3.4.1") is True
assert _is_version_reached("1.11.3.5") is True

assert _is_version_reached("1.2.3.4.1") is False
assert _is_version_reached("1.3") is False
assert _is_version_reached("1.11.3.5") is False

def test_deprecated_decorator_on_function(self) -> None:
"""Test deprecated decorator for simple function."""
Expand Down

0 comments on commit c536686

Please sign in to comment.