-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add test script that tries to import all drivers
- Loading branch information
Showing
3 changed files
with
143 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
$ErrorActionPreference = "Stop" | ||
|
||
[Ref]$Imports = 0 | ||
[Ref]$SuccessfulImports = 0 | ||
|
||
function Import-Driver { | ||
Param( | ||
[Parameter(Mandatory)] | ||
[string]$DriverName | ||
) | ||
$Imports.Value++ | ||
python ./tests/importability/import_driver.py $DriverName | ||
if ($?) { | ||
$SuccessfulImports.Value++ | ||
} | ||
} | ||
|
||
Get-ChildItem -Path src -Attributes Directory | % { Import-Driver -DriverName $_.name } | ||
|
||
if ($SuccessfulImports.Value -ne $Imports.Value) | ||
{ | ||
Throw "Only $($SuccessfulImports.Value) out of $($Imports.Value) imports were successful." | ||
} | ||
|
||
if ($SuccessfulImports.Value -eq 0) | ||
{ | ||
Throw "Could not import any drivers." | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
"""Test if an instrument driver can be imported. | ||
Usage: | ||
From the root of the repository, call | ||
`python ./tests/importability/import_driver.py <driver-name>` | ||
""" | ||
|
||
import json | ||
import logging | ||
import sys | ||
import traceback | ||
from configparser import ConfigParser | ||
from pathlib import Path | ||
|
||
import pysweepme | ||
|
||
logging.basicConfig(level=logging.DEBUG, format="%(levelname)s: %(message)s") | ||
|
||
|
||
def is_compatible(driver_name: str) -> bool: | ||
"""Check if the driver compatibility information matches the currently running python version. | ||
Args: | ||
driver_name: Name (folder) of the driver to import. | ||
""" | ||
limit_for_32_bit = 0x100000000 | ||
version = sys.version_info | ||
python_version = f"{version.major}.{version.minor}" | ||
bitness = "64" if sys.maxsize > limit_for_32_bit else "32" | ||
compatibility_flags = { | ||
"any", | ||
f"any-{bitness}", | ||
f"{python_version}-any", | ||
f"{python_version}-{bitness}", | ||
} | ||
config = ConfigParser() | ||
config.read(Path("src") / driver_name / "info.ini") | ||
# get the architecture from the run section, and if it does not exist from the info section. This is | ||
# the same order the server checks in uploaded drivers. | ||
# If no architecture is found at all, use the default "any" (as a quoted string) | ||
architecture_str = json.loads( | ||
config.get("run", "architecture", fallback=config.get("info", "architecture", fallback='"any"')), | ||
) | ||
architecture = {a.strip() for a in architecture_str.split(",")} | ||
# compatibility is given if the two sets have non-empty intersection | ||
if architecture & compatibility_flags: | ||
return True | ||
return False | ||
|
||
|
||
def import_driver(driver_name: str) -> None: | ||
"""Let pysweepme import a driver from the src directory. | ||
Args: | ||
driver_name: Name (folder) of the driver to import. | ||
""" | ||
# some devices already get an initialized (not opened) port from the PortManager and require a port string. | ||
# There is no universal port string that works for all devices, so we try a couple until we got something | ||
# that works. | ||
# We are using "" (no port), "USB" (gets initialized without any side-effects), and "0" (for Indexes, e.g. Webcam) | ||
port_strings = ["", "USB", "0"] | ||
exceptions = [] | ||
for port_string in port_strings: | ||
try: | ||
driver_instance = pysweepme.get_driver( | ||
driver_name, | ||
folder="src", | ||
port_string=port_string, | ||
) | ||
break | ||
except Exception: | ||
exceptions.append((port_string, sys.exc_info())) | ||
else: | ||
for port_string, exc in exceptions: | ||
msg = f'Failed to import {driver_name} with port string "{port_string}".' | ||
logging.error(msg) | ||
traceback.print_exception(*exc) | ||
msg = f"Driver {driver_name} could not be imported with any of the tested port_strings." | ||
raise Exception(msg) | ||
|
||
assert driver_name == driver_instance._latest_parameters["Device"] | ||
|
||
logging.debug(f"Imported {driver_name}.") | ||
|
||
|
||
try: | ||
driver_name = sys.argv[1] | ||
except IndexError as e: | ||
msg = "This script must be called with the driver name as first argument." | ||
raise IndexError(msg) from e | ||
|
||
if is_compatible(driver_name): | ||
import_driver(driver_name) | ||
else: | ||
logging.debug( | ||
f"Skipped importing {driver_name} because it is not meant to be compatible with this python version.", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
[tox] | ||
no_package = true | ||
env_list = py39-32, py39-64 | ||
skip_missing_interpreters = false | ||
|
||
[testenv] | ||
description = check if drivers can be imported | ||
basepython = | ||
py39-32: python3.9-32 | ||
py39-64: python3.9-64 | ||
allowlist_externals = pwsh | ||
deps = | ||
py39-{32,64}: -r requirements.txt | ||
passenv = | ||
LOCALAPPDATA #required for win32 certifi | ||
commands = | ||
pwsh -NoProfile -Command .\.github\Test-Importability.ps1 |