Skip to content

Commit

Permalink
Merge pull request #733 from arr-ee/655-disambiguate-bitness
Browse files Browse the repository at this point in the history
Use architecture instead of `bitness` in `LibraryPath` and friends
  • Loading branch information
MatthieuDartiailh committed Mar 28, 2023
2 parents aebdfe5 + e723d83 commit 6efceab
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 154 deletions.
9 changes: 9 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ PyVISA Changelog
-------------------
- fix ctypes truncated pointers on 64-bit for ViBusAddress, ViBusSize, ViAttrState PR # 725
- fix read_termination_context does not allow None PR # 727
- replace `bitness` for library and python runtime information with instruction set
and bitness # 733
Resulting API changes:
- `pyvisa.util.LibraryPath.arch` now returns a list of `pyvisa.util.ArchitectureType`
enum values representing architectures the binary was compiled for
- `p.u.LibraryPath.is_32bit`, `p.u.LibraryPath.is_64bit`, and `p.u.LibraryPath.bitness`
have been removed
- `p.u.get_shared_library_arch` now returns `p.u.PEMachineType` instead of a string
- `p.u.get_arch` now returns a list of `p.u.ArchitectureType`

1.13.0 (22-12-2022)
-------------------
Expand Down
2 changes: 1 addition & 1 deletion pyvisa/ctwrapper/highlevel.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def get_debug_info(cls) -> DebugInfo:
for ndx, visalib in enumerate(paths, 1):
nfo: Dict[str, Union[str, List[str]]] = OrderedDict()
nfo["found by"] = visalib.found_by
nfo["bitness"] = visalib.bitness
nfo["architecture"] = [str(a.value) for a in visalib.arch]
try:
lib = cls(visalib)
sess, _ = lib.open_default_resource_manager()
Expand Down
7 changes: 5 additions & 2 deletions pyvisa/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -730,9 +730,12 @@ def from_wrong_arch(cls, filename: str) -> "LibraryError":
filename, "user" if filename == util.read_user_library_path() else "auto"
)
s += "No matching architecture.\n"
s += " Current Python interpreter is %s bits\n" % details["bits"]
s += (
" Current Python interpreter architecture: %s\n"
% details["architecture"]
)
s += " The library in: %s\n" % visalib.path
s += " found by: %s\n" % visalib.found_by
s += " bitness: %s\n" % visalib.bitness
s += " architecture: %s\n" % [str(a.value) for a in visalib.arch]

return cls("Error while accessing %s: %s" % (filename, s))
124 changes: 59 additions & 65 deletions pyvisa/testsuite/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from configparser import ConfigParser
from functools import partial
from io import StringIO
from pathlib import Path
from types import ModuleType
from typing import Optional

Expand Down Expand Up @@ -509,80 +510,82 @@ def get_debug_info(cls):
util.system_details_to_str(details)


def generate_fakelibs(dirname):
for name, blob in zip(
[
"fakelib_bad_magic.dll",
"fakelib_good_32.dll",
"fakelib_good_64_2.dll",
"fakelib_good_64.dll",
"fakelib_good_unknown.dll",
"fakelib_not_pe.dll",
],
[
struct.pack("=6sH52sl", b"MAPE\x00\x00", 0x014C, 52 * b"\0", 2),
struct.pack("=6sH52sl", b"MZPE\x00\x00", 0x014C, 52 * b"\0", 2),
struct.pack("=6sH52sl", b"MZPE\x00\x00", 0x8664, 52 * b"\0", 2),
struct.pack("=6sH52sl", b"MZPE\x00\x00", 0x0200, 52 * b"\0", 2),
struct.pack("=6sH52sl", b"MZPE\x00\x00", 0xFFFF, 52 * b"\0", 2),
struct.pack("=6sH52sl", b"MZDE\x00\x00", 0x014C, 52 * b"\0", 2),
],
):
with open(os.path.join(dirname, name), "wb") as f:
def generate_fakelibs(dirname: Path):
libs = {
"fakelib_bad_magic.dll": struct.pack(
"=6sH52sl", b"MAPE\x00\x00", 0x014C, 52 * b"\0", 2
),
"fakelib_good_x86_32.dll": struct.pack(
"=6sH52sl", b"MZPE\x00\x00", 0x014C, 52 * b"\0", 2
),
"fakelib_good_x86_64.dll": struct.pack(
"=6sH52sl", b"MZPE\x00\x00", 0x8664, 52 * b"\0", 2
),
"fakelib_good_arm_64.dll": struct.pack(
"=6sH52sl", b"MZPE\x00\x00", 0xAA64, 52 * b"\0", 2
),
"fakelib_good_unknown.dll": struct.pack(
"=6sH52sl", b"MZPE\x00\x00", 0xFFFF, 52 * b"\0", 2
),
"fakelib_not_pe.dll": struct.pack(
"=6sH52sl", b"MZDE\x00\x00", 0x014C, 52 * b"\0", 2
),
}
for name, blob in libs.items():
with open(dirname / name, "wb") as f:
f.write(blob)
print("Written %s" % name)


class TestLibraryAnalysis(BaseTestCase):
"""Test (through monkey patching) the analysis of binary libraries."""

def test_get_shared_library_arch(self, tmpdir):
def test_get_shared_library_arch(self, tmp_path: Path):
"""Test analysing a library on Windows."""
dirname = str(tmpdir)
generate_fakelibs(dirname)

for f, a in zip(["_32", "_64", "_64_2"], ["I386", "IA64", "AMD64"]):
arch = util.get_shared_library_arch(
os.path.join(tmpdir, "fakelib_good%s.dll" % f)
)
generate_fakelibs(tmp_path)

for f, a in zip(
["x86_32", "x86_64", "arm_64"],
[
util.PEMachineType.I386,
util.PEMachineType.AMD64,
util.PEMachineType.AARCH64,
],
):
arch = util.get_shared_library_arch(tmp_path / f"fakelib_good_{f}.dll")
assert arch == a

arch = util.get_shared_library_arch(
os.path.join(dirname, "fakelib_good_unknown.dll")
)
assert arch == "UNKNOWN"
arch = util.get_shared_library_arch(tmp_path / "fakelib_good_unknown.dll")
assert arch == util.PEMachineType.UNKNOWN

with pytest.raises(Exception) as e:
util.get_shared_library_arch(os.path.join(dirname, "fakelib_bad_magic.dll"))
util.get_shared_library_arch(tmp_path / "fakelib_bad_magic.dll")
assert "Not an executable" in e.exconly()

with pytest.raises(Exception) as e:
util.get_shared_library_arch(os.path.join(dirname, "fakelib_not_pe.dll"))
util.get_shared_library_arch(tmp_path / "fakelib_not_pe.dll")
assert "Not a PE executable" in e.exconly()

def test_get_arch_windows(self, tmpdir):
def test_get_arch_windows(self, tmp_path: Path):
"""Test identifying the computer architecture on windows."""
dirname = str(tmpdir)
generate_fakelibs(dirname)
generate_fakelibs(tmp_path)

platform = sys.platform
sys.platform = "win32"
try:
for f, a in zip(
["_32", "_64", "_64_2", "_unknown"], [(32,), (64,), (64,), ()]
["x86_32", "x86_64", "arm_64", "_unknown"],
[
[util.ArchitectureType.I386],
[util.ArchitectureType.X86_64],
[util.ArchitectureType.AARCH64],
[],
],
):
print(f, a)
path = os.path.join(dirname, "fakelib_good%s.dll" % f)
lib = util.LibraryPath(path)
path = tmp_path / f"fakelib_good_{f}.dll"
lib = util.LibraryPath(str(path))
assert lib.arch == a
if f != "_unknown":
assert lib.is_32bit if 32 in a else not lib.is_32bit
assert lib.is_64bit if 64 in a else not lib.is_64bit
assert lib.bitness == ", ".join(str(b) for b in a)
else:
assert lib.is_32bit == "n/a"
assert lib.is_64bit == "n/a"
assert lib.bitness == "n/a"
finally:
sys.platform = platform

Expand All @@ -601,19 +604,16 @@ def alt_run(*args, **kwargs):
subprocess.run = alt_run

for p, f, a in [
("linux2", "32-bit", (32,)),
("linux2", "32-bit & 64-bit", (32, 64)),
("linux3", "64-bit", (64,)),
("darwin", "(for architecture i386)", (32,)),
("darwin", "(for architecture x86_64)", (64,)),
("linux", "80386", [(util.ArchitectureType.I386)]),
("linux", "x86-64", [(util.ArchitectureType.X86_64)]),
("linux", "aarch64", [(util.ArchitectureType.AARCH64)]),
("darwin", "executable i386", [(util.ArchitectureType.I386)]),
("darwin", "executable x86_64", [(util.ArchitectureType.X86_64)]),
("darwin", "executable arm64", [(util.ArchitectureType.AARCH64)]),
]:
sys.platform = p
lib = util.LibraryPath(f)
assert lib.arch == a
assert lib.is_32bit if 32 in a else not lib.is_32bit
assert lib.is_64bit if 64 in a else not lib.is_64bit
assert lib.bitness == ", ".join(str(b) for b in a)

finally:
sys.platform = platform
subprocess.run = run
Expand All @@ -625,10 +625,7 @@ def test_get_arch_unix_unreported(self):
try:
sys.platform = "darwin"
lib = util.LibraryPath("")
assert lib.arch == ()
assert lib.is_32bit == "n/a"
assert lib.is_64bit == "n/a"
assert lib.bitness == "n/a"
assert lib.arch == []
finally:
sys.platform = platform
subprocess.run = run
Expand All @@ -640,10 +637,7 @@ def test_get_arch_unknown(self):
try:
sys.platform = "test"
lib = util.LibraryPath("")
assert lib.arch == ()
assert lib.is_32bit == "n/a"
assert lib.is_64bit == "n/a"
assert lib.bitness == "n/a"
assert lib.arch == []
finally:
sys.platform = platform
subprocess.run = run

0 comments on commit 6efceab

Please sign in to comment.