pax_global_header00006660000000000000000000000064137516532760014531gustar00rootroot0000000000000052 comment=d822b324562ff5761bcf1017addaf2dc47b6cad8 pyvisa-1.11.3/000077500000000000000000000000001375165327600131275ustar00rootroot00000000000000pyvisa-1.11.3/.coveragerc000066400000000000000000000005361375165327600152540ustar00rootroot00000000000000[run] branch = True include = */pyvisa/* omit = */pyvisa/testsuite/* */pyvisa/thirdparty/* [report] # Regexes for lines to exclude from consideration exclude_lines = # Have to re-enable the standard pragma pragma: no cover # Don't complain if tests don't hit defensive assertion code: raise NotImplementedError pass pyvisa-1.11.3/.github/000077500000000000000000000000001375165327600144675ustar00rootroot00000000000000pyvisa-1.11.3/.github/ISSUE_TEMPLATE/000077500000000000000000000000001375165327600166525ustar00rootroot00000000000000pyvisa-1.11.3/.github/ISSUE_TEMPLATE/bug_report.md000066400000000000000000000006211375165327600213430ustar00rootroot00000000000000--- name: Bug report about: Create a report to help us improve title: '' labels: '' assignees: '' --- To Reproduce -------------- Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error **Output of `pyvisa-info`** pyvisa-1.11.3/.github/ISSUE_TEMPLATE/instrument-communication-issue.md000066400000000000000000000014771375165327600254060ustar00rootroot00000000000000--- name: Instrument communication issue about: Template for requesting help communcating with a specific instrument title: "[COM] Communication issue with XXX using XXX" labels: instrument assignees: '' --- Instrument details ------------------ * Model: * Communication: TCPIP, GPIB, .... * Link to the documentation (if available): Output of `pyvisa-info` ----------------------- pyvisa-1.11.3/.github/PULL_REQUEST_TEMPLATE.md000066400000000000000000000023141375165327600202700ustar00rootroot00000000000000 - [ ] Closes # (insert issue number if relevant) - [ ] Executed ``black . && isort -c . && flake8`` with no errors - [ ] The change is fully covered by automated unit tests - [ ] Documented in docs/ as appropriate - [ ] Added an entry to the CHANGES file pyvisa-1.11.3/.github/workflows/000077500000000000000000000000001375165327600165245ustar00rootroot00000000000000pyvisa-1.11.3/.github/workflows/ci.yml000066400000000000000000000043751375165327600176530ustar00rootroot00000000000000name: Continuous Integration on: schedule: - cron: '0 0 * * 2' push: branches: - master - staging - trying pull_request: branches: - master paths: - .github/workflows/ci.yml - pyvisa/* - pyproject.toml - setup.cfg - setup.py jobs: formatting: name: Check code formatting runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Set up Python uses: actions/setup-python@v1 with: python-version: 3.8 - name: Install tools run: | python -m pip install --upgrade pip pip install flake8 black isort mypy pytest - name: Isort run: | isort pyvisa -c; - name: Black run: | black pyvisa --check; - name: Flake8 run: | flake8 pyvisa; - name: Mypy run: | mypy pyvisa; tests: name: Unit tests runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] python-version: [3.6, 3.7, 3.8, 3.9] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v1 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | python -m pip install --upgrade pip - name: Install project run: | pip install -e . - name: Test with pytest run: | pip install pytest-cov pytest --pyargs pyvisa --cov pyvisa --cov-report xml -v - name: Upload coverage to Codecov uses: codecov/codecov-action@v1 with: token: ${{ secrets.CODECOV_TOKEN }} flags: unittests name: codecov-umbrella fail_ci_if_error: true # Added to summarize the matrix (otherwise we would need to list every single # job in bors.toml) tests-result: name: Tests result if: always() needs: - tests runs-on: ubuntu-latest steps: - name: Mark the job as a success if: needs.tests.result == 'success' run: exit 0 - name: Mark the job as a failure if: needs.tests.result != 'success' run: exit 1pyvisa-1.11.3/.github/workflows/docs.yml000066400000000000000000000016541375165327600202050ustar00rootroot00000000000000name: Documentation building on: schedule: - cron: '0 0 * * 2' push: branches: - master - staging - trying pull_request: branches: - master paths: - .github/workflows/docs.yml - pyvisa/* - docs/* - setup.py jobs: docs: name: Docs building runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Set up Python uses: actions/setup-python@v1 - name: Install dependencies run: | python -m pip install --upgrade pip - name: Install project run: | python setup.py develop - name: Install graphviz uses: kamiazya/setup-graphviz@v1 - name: Install doc building tools run: | pip install sphinx sphinx_rtd_theme - name: Build documentation run: | mkdir docs_output; sphinx-build docs/source docs_output -W -b html; pyvisa-1.11.3/.gitignore000066400000000000000000000003111375165327600151120ustar00rootroot00000000000000*~ __pycache__ *egg-info* *.pyc .DS_Store docs/_build/ .idea build/ dist/ MANIFEST .tox .coverage .eggs # WebDAV file system cache files .DAV/ _test/ .vscode htmlcov/ .mypy_cache/ pip-wheel-metadata/ pyvisa-1.11.3/.pre-commit-config.yaml000066400000000000000000000007331375165327600174130ustar00rootroot00000000000000repos: - repo: https://github.com/pre-commit/mirrors-isort rev: v5.5.3 hooks: - id: isort - repo: https://github.com/psf/black rev: 20.8b1 hooks: - id: black language_version: python3.7 - repo: https://gitlab.com/pycqa/flake8 rev: 3.8.3 hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy rev: v0.782 # Use the sha / tag you want to point at hooks: - id: mypy additional_dependencies: [numpy, typing_extensions]pyvisa-1.11.3/AUTHORS000066400000000000000000000020501375165327600141740ustar00rootroot00000000000000PyVISA was originally programmed by Torsten Bronger and Gregor Thalhammer, Innsbruck, Austria. It is based on earlier experiences by Thalhammer. It was maintained from March 2012 to August 2013 by Florian Bauer. It is currently maintained by Hernan E. Grecco . Other contributors, listed alphabetically, are: * bauflo3 * bkstein * bronger> * Christian Lupien * Colin Marquardt * crazyfermions * gnbl * Gregor Thalhammer * HummingBrid * kcsaff * Neil J. Jansen * Laurent P. René de Cotret * Martin Ritter * Matthew94 * Matthieu Dartiailh * mordoror * Tobias Müller * Yves Delley If you think your name should be here, please let me know. pyvisa-1.11.3/CHANGES000066400000000000000000000427531375165327600141350ustar00rootroot00000000000000PyVISA Changelog ================ 1.11.3 (07-11-2020) ------------------- 1.11.2 was skipped due to an issue in the MANIFEST file. - fix MANIFEST to exclude built docs - fix minor typos in deprecation warning for GPIB resources - generate some test files on the fly to avoid issue when building conda packages - add official Python 3.9 support 1.11.1 (30-09-2020) ------------------- - deprecate methods that were mistakenly added to GPIB::INSTR resources PR #560 - fix the listing of available backends (Also not that we now return the backend name as can be used to create a ResourceManger) PR #545 - allow a None value for the board value of a ResourceInfo PR #547 This allows for funky resource name such ASRL/dev/tty0::INSTR which are common in pyvisa-py and avoid returning a completely generic resource in those cases. 1.11 (16-09-2020) ----------------- PyVISA 1.11 introduces a small backward incompatibility in the handling of the arguments to handlers for VISA events. The old system was tightly linked to the ctwrapper and not really usable as it was. As a consequence we pass the contents of the ctypes objects to the handler rather than the bare ctypes object (with the exception of the user handle for which there is no way to do it properly). This is a breaking change and if your code is affected you can revert to the old behavior by setting the environment variable PYVISA_WRAP_HANDLER=0 or set ctwrapper.WRAP_HANDLER to False but please consider updating to the new behavior. PyVISA 1.11 also removes deprecated functions and attributes that were supposed to be removed in 1.10: - `ask`: use `query` instead - `ask_delay`: use `query_delay` - `ask_for_values`: use either `query_ascii_values` or `query_binary_values` as relevant - `write_values`: use either `write_ascii_values` or `write_binary_values` as relevant - `read_values`: use either `read_ascii_values` or `read_binary_values` as relevant - `query_values`: use either `query_ascii_values` or `query_binary_values` as relevant - `values_format`: has no equivalent simply pass the proper argument to either the ascii or binary variant of the function (`read_xxxx_values`, `write_xxxx_values`, `query_xxxx_values`) - Add support for "s" and "p" binary format which can be used to retrieve binary files from instruments. PR #536 - Convert the testsuite to use pytest PR #531 This is motivated by the possibility to re-use it in PyVISA-py. However since unittest use inheritance to detect tests, doing so would have been clunky, pytest name base detection works better for that purpose. - Setup Azure pipelines for self-hosted runner using Keysight tools to run an extended set of tests. PR #531 - Introduce an enumeration for special VISA timeout values PR #531 - Provide VisaLibraryBase.handle_return_value to ease the handling of return values in alternative backends PR #525 - Transition to using dataclasses for resource name PR #525 This is NOT fully backward compatible if you used to index the resource name - Allow alternative backends to use an _ instead of a - in their name PR #525 - Add Event class to provide a nice interface to VISA events PR #511 - Add `wrap_handler` to provide a nicer way to write event handler PR #511 - Add wrapper classes for events PR #511 - Add typing to the entire codebase PR #511 - Use black and isort on the code to homogenize style PR #511 - Convert docstrings to use numpy formatting PR #511 - Explicitly set attributes on resources to make the code more readable PR #511 - Make MessageBasedResource.read_bytes break on message end when `break_on_termchar` is True PR #511 - Add support for dll_extra_paths in .pyvisarc to provide a way to specify paths in which to look for dll on Windows and Python >= 3.8 PR #509 - Drop Python 2 support PR #486 - Limit support to Python 3.6+ PR #486 - Improve the test suite and introduce tests relying on Keysight Virtual instrument software PR #486 - Add badges to the README PR #486 - Improve ResourceManager.list_opened_resource to list only open resources. Previously all resources created and not yet garbage collected were listed. PR #486 - Always normalize resource names PR #486 - Treat floating points number as double when parsing ASCII data blocks PR #486 - Allow bound methods as handler function (the use of is in tests prevented it) PR #486 - Deprecate some unused functions found in the util.py module PR #486 - Warn or raise if the beginning of a binary block is not found among the first characters. The default value is 25. PR #486 - Make the library less biased towards National Instrument by referring to IVI where relevant. In particular rename the @ni backend to @ivi PR #456 - Deprecate the `visa` module that is causing issue with the VISA payment processing package PR #448 1.10.1 (2019-09-11) ------------------- - Fix reading binary values with an empty header PR #454 - Allow to use different headers in write_binary_values PR #454 - Remove `delay` kwarg from `read_ascii_values` which should never have been there PR #454 - Clarify the documentation about open_timeout PR #451 1.10 (2019-08-09) ----------------- - Change the returned data_length for IEEE block of undefined size to 0 PR #435 - Add chunk_size and data_length keyword argument to read/query_binary_values PR #435 - Make the ordering of the visa library deterministic PR #399 - Properly close pipes when looking for a shared library path on linux #380 - Fixing missing argument for USBInstrument.usb_control_out PR #353 - avoid attempting to close already closed resources in del PR #424 - add a list_opened_resources method to the ResourceManager PR #415 - use privately stored resource name in Resource class rather than relying on VisaLibrary PR #415 - keep track of resources created by the ResourceManager to properly close them PR #357 - replace time.clock by time.perf_counter under Python 3 PR #441 - make the ordering of the visa library deterministic PR #399 - properly close pipes when looking for a shared library path on linux #380 - fixing missing argument for USBInstrument.usb_control_out PR #353 - usb_control_out -> control_out. warnings for deprecated usb_control_out PR #353 - Added new function log_to_stream() PR #363 - Made all enumerations of the `constants` module unique. Fixed duplicate enums in StatusCode PR #371 - Use ni backend when specifying a file in open_visa_library PR #373 - Add flush() method to all resource classes that support viFlush() (with the exception of VXIInstrument class) PR #390 1.9.1 (2018-08-13) ------------------ - Add expect_termination argument to read_binary_values and query_binary_values. This allows to retain the behavior of these methods from pyvisa 1.8, where the length of the block of values that is being read did not include the very final read termination. For instruments omitting the termination character when transferring binary data, visa library raises a timeout exception in case pyvisa 1.9.0 is used. Note that the behavior is not reverted completely to its pyvisa 1.8 state because for other instruments (for example, Keysight PNA on Ethernet) the termination character is indeed added at the end of the message, and is not counted in the declared length in the header. Prior to 1.9, if the last character of the binary block is also the termination character, the actual termination could be missed, which leads to hard to debug bugs hence the choice to preserve 1.9 behavior by default. PR #349 - fix an encoding handling issue in setup.py PR #343 - if installed use pyvisa-py backend if a binary VISA implementation is not installed. PR #341 - make custom exception hashable by removing __eq__. This should not impact user code. PR #340 - fix an issue with the default value for GPIB secondary address in rname.py PR #336 - ensure docstrings exist before manipulating them (attributes.py) PR #318 - documentation improvements PR #320 #323 1.9 (2017-02-25) ---------------- - Drop support for Python 2.6, 3.2 and 3.3 PR #300 - add the missing read_binary_values and read_ascii_values (PR #301) - deprecate old methods in MessageBased (ask, read_values, query_values, write_values, ask_delay) (PR #301) - add support for hp headers in binary data (PR #301) - fix encoding issue in write_ascii_values (PR #301) - use import to load backend rather than pkgutil.iter_modules. This allows PyVISA to support PyInstaller PR #307 - improvements to the visa shell: attributes type conversion (PR #299), termchar command (PR #285), timeout command (PR #284), support for non-default backend (PR #283), console script pyvisa-shell (PR #286) - improve speed for large data transfer by using bytearray instead of bytes (PR #282) - make Resource a context manager closing it. (PR #255) - add 64 bits version of registry based functions (PR #278) - make exceptions pickable (PR #249) - add resource_name to the output of parse_resource_extended (PR #238) - fix wait_on_event behavior in case of timeout (PR #234) - allow selecting the backend using the PYVISA_LIBRARY env var (PR #195) 1.8 (2015-08-24) ---------------- - Fixed error reporting with Unicode filenames. (Issue #136) - Improved documentation. - Clarify timeout getter and setter. (Issue #167) - In open_resource, return a Resource object and warns if resource class not registered. - Register resource class for empty resource class. - Allow registering parent resource classes. - Changed types in wrapper to be platform independent (viStatus is always 32 bit). (Issue #134) - Fix a not a invalid EventType bug. (Thanks lupien) - Added optional resource_pyclass to open_resource. - Fixed bug in serial flush. (Thanks bkstein) - Implemented resource name parsing in pure python. 1.7 (2015-05-16) ---------------- - Removed find_next and find_resources from VisaLibraryBase. (Issue also #135, thanks) - Implemented parse_resource and parse_resource_extended. - Created rname module to parse Resource Names. - Properly cleanup visa handlers upon resource close. (thanks lupien) - Improved gpib classes (thanks lupien) - Fixed bug in binary data writing. (Issue #140, thanks burnpack) - Fix reseting of line termination for serial. (Issue #147, thanks lupien) - Added property to resource name returning the InterfaceType value. - Added backend information to logging. - Added the flow_control attribute to ASRL resources. (Issue #144, thanks lupien) - Remove empty entry in resources caused by attribute registration. (Issue #144, thanks lupien) - Make container=numpy.array work consistently. (Issue #142, thanks Martin Ritter) - Create compact/struct.py for python2/3 compatibility. (thanks Martin Ritter) - Improve install and uninstall handlers (Issue #138, #139, #151 thanks lupien) - Prevents cygwin segfaults. (Issue #131) - Better error reporting when a resource cannot be found. (Issue #129) - Suppress VI_SUCCESS_MAX_CNT warning on read raw. (Issue #116) - Implemented smarter query values based on looking how many bytes are expected. (Issue #118) - Fix UnicodeDecodeError on wrong file for library load (Issue #136, thanks lupien) 1.6.3 (2015-02-08) ------------------ - Added support to Rhode and Schwartz Passport driver. (Issue #115) - Fixed access to the interface_type property. (Issue #114, thanks mordoror) - Imported constants module in visa module. (Issue #72) 1.6.2 (2014-12-29) ------------------ - Proper handling of VI_ERROR_RSRC_NFOUND. - Added conditional dependency for unittest2 in Python2.6 (Issue #107) - Fixed Shell on Windows. (Issue #101) - Moved Lantz Shell to PyVISA. - Easier way to get debug information. - Better debug info for backends. 1.6.1 (2014-10-28) ------------------ - Add ignore_warning methods to Resource and ResourceManager. - Added more formats to binary values. (Issue #92) - Fixed exception raising in legacy read_values. (Issue #91) - Provide a backend hook to display debug info. - Better debug info for binary libraries. - Fixed exceptions formatting (thanks Matthew94) 1.6 (2014-09-28) ---------------- - 13 Resource Classes covering all resource types. - Attributes classes provided introspection to VISA attributes. - Many VISA attributes added to Resource Classes. - Use of IntEnum for common constants. - Better documentation. - Implementation of discoverable backends. - New functions to encode and decode of IEEE blocks. - New functions to encode and decode of ASCII blocks. - New API to transfer values from the instrument. - Renamed ask/ask_delay/ask_for_values to ask/query_delay/query_values. Old names still available for backwards compatibility. - Implemented Group Execute Trigger for GPIBInterface. (Issue #67) - Make setuptools a requirement. (Issue #64 and 68) - Simplified testing. - Removed legacy subpackage. - Removed string handling wrappers. - Removed Instrument class in favour of Resource. - Removed status and implemented thread-safe, per instrument, last_status. - Refactored warning ignoring mechanisms to a thread-safe one. - Added enum34 requirement for Python < 3.4. - Removed deprecated term_chars. 1.5 (2014-06-24) ---------------- - Python 3.2+ compatibility. (Issue #32) - Change source encoding to utf-8. - Reorganized package structure. (Issue #13) - Improved installation. - Moved tests inside the package. - Added CI using Travis. - Created new wrapper for the underlying library. - Moved vpp43 code to legacy subpackage. - Moved documentation to readthedocs. - Make documentation mobile-friendly. (Issue #2) - Removed latex documentation. - ResourceManager is no longer a singleton. (Issue #8) - VisaLibrary is no longer a singleton. (Issue #7) - VISA functions are VisaLibrary methods. (Issue #11) - Improved detection of VISA library path in all OS. - Added diagnostics functions to help debugging. - Added extensive logging to help debugging. (Issue #12) - Improved error messages. - Added encoding parameter to read and write. (Issue #38) - Added termination parameter to read and write. (Issue #38) - Added size to read_raw. (Issue #37) - Removed delay parameter in favor of ask_delay (Issue #34) - Added 64 bits VISA library methods. - Cleaned up code. 1.4 (2012-05-13) ---------------- - add coverage - add tox testing 1.3 (2008-03-26) ---------------- - Changed licence to MIT. - Made determination of resource class even more careful. 1.2 (2007-09-19) ---------------- - Changed some __getattr__ to getattr in order to have working exceptions again (e.g. timeouts) in vpp43 - Softened the test for "INSTR" even further. Introduced the "stb" property for GPIB instruments. - Changed "is not an INSTR" error to a warning. - Added correct prefix for RPM in setup.cfg. 1.1 (2006-11-21) ---------------- - Mentioned possible AttributeError with viParseRsrcEx. - Made secure against missing viParseRsrcEx. - Removed superfluous calls to parse_resource_extended. - setup.py Script can now handle installation with or without setuptools. - setup.py: Switched to new distutils version. 1.0 (2006-01-23) ---------------- - New properties of SerialInstrument explained. - Added many further properties to SerialInstrument. 0.9.7 (2005-09-21) ------------------ - Renamed timeout parameter in open() to open_timeout. - Renamed Timeout parameter in open() to open_timeout. - Added section about SerialInstrument. - Added class SerialInstrument. Made termination characters even more robust. 0.9.6 (2005-08-31) ------------------ - Renamed TypeError to VisaTypeError. - Added InvalidBinaryFormat. Renamed TypeError to VisaTypeError. - Added a lot of docstrings. Fixed bug with ValueError exception raising. - Eliminated string exceptions. A little bit of code clean-up. - Added old distutils inclusion for RPM that cause trouble with my setuptools installation. - Set default for term_chars to None and implemented it in write() method. - Described new default for term_chars. - Added instrument(). Fixed bugs in __repr()__. - Improved documentation. - Switched from distutils to setuptools. 0.9.5 (2005-08-27) ------------------ - Changed package name to "PyVISA". - visa_attributes.py: 0xFFFFFFFF -> 0xFFFFFFFFL. - Switched from distutils to setuptools. 0.9.4 (2005-08-12) ------------------ - Added filename selection for VISA DLL with Windows in vpp43.py. - Added code to skip over header before binary data. - Cleaned up whitespace. - Added support for endianess in case of binary transfers. - Improved binary reading; now it also accepts things like "#267...". 0.9.3 (2005-07-21) ------------------ - Changed default termination characters to "" for GPIB instruments. LF and CR are completely stripped from the end of read string, no matter how the termination characters are set. 0.9.2 (2005-07-19) ------------------ - Added remaining keyword arguments for Instrument constructor. Added CR and LF. Added working support for reading binary data. - Added ask() and ask_for_values(). - Partially implemented binary reading. - Split the old term_chars in term_chars, delay, and send_end. - Implemented warning system for invalid keyword arguments. Added test for valid float values in read_floats(). Added full term_char string in __get_term_char(). - Standard timeout increased from 2 to 5 seconds. - read_floats() returns *always* a list. - Moved trigger() method to Instrument class. - Fixed bug in regular expression for termination characters. - Fixed bug with ignored term_char attribute for GPIB instruments. - Increased chunk_size's default value and added it to the keyword arguments of the constructor. 0.9.1 (2005-07-03) ------------------ - Added properties resource_name and resource_class to ResourceTemplate. Used both to simplify code. 0.9 (2005-06-29) ---------------- - First usable release. See ChangeLog for more information. pyvisa-1.11.3/ChangeLog000066400000000000000000000671641375165327600147170ustar00rootroot000000000000002008-03-26 Torsten Bronger * doc/pyvisa.tex, doc/vpp43.txt, src/__init__.py, src/visa.py, src/visa_attributes.py, src/visa_exceptions.py, src/visa_messages.py, src/visa_study.py, src/vpp43.py, src/vpp43_attributes.py, src/vpp43_constants.py, src/vpp43_types.py, test/test_itc4.py, test/test_keithley2000.py, COPYING, PyVISA.egg-info/PKG-INFO, doc/LICENSE, doc/homepage.txt, setup.py: Updated to v1.3. Changed licence to MIT. 2008-02-08 Torsten Bronger * src/visa.py: Made determination of ressource class even more careful. 2007-09-19 Torsten Bronger * src/visa.py: Tiny improvement. * doc/pyvisa.tex, setup.py: Promoted to version 1.2 * doc/homepage.txt: Minor correction. 2007-05-03 Torsten Bronger * src/vpp43.py: Changed some __getattr__ to getattr in order to have working exceptions again (e.g. timeouts). * src/visa.py: Softened the test for "INSTR" even further. Introduced the "stb" property for GPIB instruments. 2007-01-13 Torsten Bronger * src/visa.py: Changed "is not an INSTR" error to a warning. 2006-12-09 Torsten Bronger * setup.cfg: Added correct prefix for RPM. 2006-11-24 Torsten Bronger * doc/homepage.txt: Deleted "purchase" thing. 2006-11-21 Torsten Bronger * doc/pyvisa.tex: Small corrections. * PyVISA.egg-info/PKG-INFO, PyVISA.egg-info/SOURCES.txt: Ordinary update. * setup.py: Changed version number to 1.1. * doc/homepage.txt: Updated date. * doc/Makefile: An neue mkhowto-Version angepaßt. 2006-11-02 Torsten Bronger * doc/pyvisa.tex: Improved description of values_format. * doc/pyvisa.tex: Typo fixed. Promoted version to 1.1. 2006-08-13 Torsten Bronger * src/visa.py: Typo fixed. 2006-08-11 Torsten Bronger * src/vpp43.py: Added missing self. * src/vpp43.py: Now almost all VISA function may be missing (in case of very old libraries). * doc/vpp43.txt: Mentioned possible AttributeError with viParseRsrcEx. * src/vpp43.py, src/visa.py: Made secure against missing viParseRsrcEx. * src/visa.py: Removed superfluous calls to parse_resource_extended. 2006-07-28 Torsten Bronger * src/vpp43.py: Typo fixed (thanks to Steve MULLER). 2006-02-18 Torsten Bronger * doc/homepage.txt: Typo fixed. 2006-01-26 Torsten Bronger * doc/homepage.txt: Typo corrected. * doc/homepage.txt: Made introduction more positive. 2006-01-24 Torsten Bronger * PyVISA.egg-info/SOURCES.txt: New file. * PyVISA.egg-info/PKG-INFO: Ordinary update. * doc/pyvisa.tex: Minor improvements. * setup.py: Script can now handle installation with or without setuptools. * setup.py: Switched to new distutils version. 2006-01-23 Torsten Bronger * setup.py: General update. * misc/ctypes/vpp43_types.py, test/test_itc4.py, test/test_keithley2000.py, src/visa_exceptions.py, src/visa_messages.py, src/vpp43.py, src/vpp43_attributes.py, src/vpp43_constants.py, src/vpp43_types.py, src/__init__.py, src/visa.py, doc/vpp43.txt: Copyright updated. * doc/pyvisa.tex: Copyright updated. Version number changed. * doc/vpp43.txt, doc/homepage.txt: Copyright year updated. 2005-09-24 Torsten Bronger * doc/pyvisa.tex: Minor improvements. * PyVISA.egg-info/PKG-INFO: Ordinary update. * doc/homepage.txt: Mentioned that you may have to purchase the VISA library. 2005-09-23 Torsten Bronger * src/visa.py: Fixed two bugs. 2005-09-22 Torsten Bronger * doc/pyvisa.tex: New properties of SerialInstrument explained. * src/visa.py: Added many further properties to SerialInstrument. 2005-09-21 Torsten Bronger * doc/.cvsignore, PyVISA.egg-info/PKG-INFO: Ordinary update. * doc/pyvisa.tex, setup.py: Changed version number to 0.9.7. * doc/vpp43.txt: Renamed timeout parameter in open() to open_timeout. * doc/homepage.txt: Link zu pyvLab hinzugefügt. * src/vpp43.py: Renamed Timeout parameter in open() to open_timeout. * doc/pyvisa.tex: Added section about SerialInstrument. Minor improvements. * src/visa.py: Added class SerialInstrument. Made termination characters even more robust. Minor improvements. * doc/pyvisa.tex: {read,ask_for}_floats --> {read,ask_for}_values. 2005-09-18 Torsten Bronger * src/visa.py: Minor improvements. 2005-09-07 Torsten Bronger * doc/pyvisa.tex: Added index entries. 2005-09-02 Torsten Bronger * doc/pyvisa.tex: Changed document structure a lot (to allow for an index). 2005-08-31 Torsten Bronger * setup.py, doc/pyvisa.tex: Changed version number to 0.9.6. * src/vpp43.py: Renamed TypeError to VisaTypeError. * src/visa_exceptions.py: Added InvalidBinaryFormat. Renamed TypeError to VisaTypeError. * src/visa.py: Added a lot of docstrings. Fixed bug with ValueError exception raising. * src/visa.py: Eliminated string exceptions. A little bit of code clean-up. 2005-08-27 Torsten Bronger * setup.py: Added old distutils inclusion for RPM that cause trouble with my setuptools installation. * src/visa.py: Set default for term_chars to None and implemented it in write() method. * doc/pyvisa.tex: Described new default for term_chars. * src/visa.py: Added instrument(). Fixed bugs in __repr()__. 2005-08-26 Torsten Bronger * doc/pyvisa.tex: Changed section order a little bit. Added section about VISA resource names. Added description of instrument(). 2005-08-13 Torsten Bronger * doc/homepage.txt: Changed title and inverted first enumeration. * doc/Makefile: Added a "keywords" meta tag to index.html. 2005-08-12 Torsten Bronger * src/visa_attributes.py: 0xFFFFFFFF -> 0xFFFFFFFFL * doc/homepage.txt: Minor improvement. * .cvsignore: Removed Python Eggs directory. * doc/pyvisa.tex: Changed version number to 0.9.5. * setup.py: Switched from distutils to setuptools. * PyVISA.egg-info/depends.txt, PyVISA.egg-info/top_level.txt, PyVISA.egg-info/PKG-INFO: New file. 2005-08-11 Torsten Bronger * setup.py: Changed package name to "PyVISA". Changed version number to 0.9.5. * .cvsignore: Added PyVISA.egg-info. * doc/homepage.txt: Made it more friendly. * doc/pyvisa.tex: Included positive user reports. 2005-08-09 Torsten Bronger * test/test_itc4.py, test/test_keithley2000.py, src/__init__.py, src/visa.py, src/visa_exceptions.py, src/visa_messages.py, src/vpp43.py, src/vpp43_types.py, setup.py: Removed tabs from indentation. 2005-08-08 Torsten Bronger * doc/pyvisa.tex: Added note about escaping in Windows-style paths. 2005-08-02 Torsten Bronger * doc/pyvisa.tex: Mentioned too old ctypes in Enthought Python. * doc/pyvisa.tex: Added explanation about how to set the VISA libaray within the Python program. * setup.py: Changed version number to 0.9.4. 2005-07-28 Torsten Bronger * doc/pyvisa.tex: Minor corrections. * doc/pyvisa.tex: Explained INI file for Windows. Explained selecting the DLL's filename under Windows. * src/vpp43.py: Added filename selection for VISA DLL with Windows. 2005-07-22 Torsten Bronger * doc/pyvisa.tex: Various improvements. * doc/pyvisa.tex: Changed version number to 0.9.4. Changed order of properties/keyword arguments. Modified more complex example to SCPI code. 2005-07-21 Torsten Bronger * src/visa.py: Added code to skip over header before binary data. * doc/pyvisa.tex: Added explanation of endianness. * src/visa.py: Cleaned up whitespace. * src/visa.py: Added support for endianess in case of binary transfers. * src/visa.py: Improved binary reading; now it also accepts things like "#267...". 2005-07-20 Torsten Bronger * doc/vpp43.txt: Deleted document version number. * setup.py: Changed version number to 0.9.3. * doc/pyvisa.tex: Changed version number to 0.9.3. Added description of read_raw(). Updated description of termination characters. * src/visa.py: Added read_raw(). * src/visa.py: Changed default termination characters to "" for GPIB instruments. LF and CR are completely stripped from the end of read string, no matter how the termination characters are set. * doc/homepage.txt: Moved PyVISA section to the beginning. 2005-07-19 Torsten Bronger * doc/pyvisa.tex: Added optional "format" arguments. Fixed typo. * doc/pyvisa.tex: Explained missing properties of Instrument. Added explanation of values_format. Added descriptions for ask() and ask_for_values(). * src/visa.py: Added remaining keyword arguments for Instrument constructor. Added CR and LF. Added working support for reading binary data. 2005-07-18 Torsten Bronger * src/visa.py: Added ask() and ask_for_values(). * src/visa.py: Implemented binary reading. Not working yet. * doc/pyvisa.tex: Explained new keyword arguments. * src/visa.py: Split the old term_chars in term_chars, delay, and send_end. 2005-07-17 Torsten Bronger * src/visa.py: Implemented warning system for invalid keyword arguments. Added test for valid float values in read_floats(). Added full term_char string in __get_term_char(). 2005-07-13 Torsten Bronger * doc/pyvisa.tex: Standard timeout increased from 2 to 5 seconds. read_floats() returns *always* a list. Moved trigger() method to Instrument class. * src/visa.py: Standard timeout increased from 2 to 5 seconds. read_floats() returns *always* a list. Moved trigger() method to Instrument class. Fixed bug in regular expression for termination characters. Fixed bug with ignored term_char attribute for GPIB instruments. 2005-07-09 Torsten Bronger * setup.py, doc/pyvisa.tex: Changed to new release number. * src/__init__.py: minor improvement. * src/visa.py: Increased chunk_size's default value and added it to the keyword arguments of the constructor. * doc/pyvisa.tex: Added explanation of chunk_size. 2005-07-03 Torsten Bronger * doc/pyvisa.tex: Spell-checked. * doc/pyvisa.tex: Added RS232 example. * doc/pyvisa.tex, setup.py: Changed version number to 0.9.1. * README: Corrected package name. * misc/ctypes/vpp43_types.py, setup.py, src/__init__.py, src/visa_exceptions.py, src/visa_messages.py, src/visa_study.py, src/vpp43.py, src/vpp43_attributes.py, src/vpp43_constants.py, src/vpp43_types.py, test/test_keithley2000.py: Corrected package name in copyright notice. * doc/homepage.txt: Added "GPIB" to the homepage's title. * test/test_itc4.py: New file. * doc/pyvisa.tex: Adjusted to the fact that PyVISA is now also tested with RS232. Changed date. * src/visa.py: Fixed minor bug with obsolete variable name. * src/visa.py: Added properties resource_name and resource_class to ResourceTemplate. Used both to simplify code. 2005-07-01 Torsten Bronger * setup.py: Made description even shorter. * doc/homepage.txt: Made the string "GPIB" more obvious on the homepage. 2005-06-30 Torsten Bronger * README: Undated to current situation. * setup.py: Changed description. 2005-06-29 Torsten Bronger * setup.py, doc/pyvisa.tex: Changed to version 0.9. * doc/vpp43.txt: Minor fix. * test/test_keithley2000.py: Fixed bug with variable "voltages". 2005-06-28 Torsten Bronger * doc/vpp43.txt: Added explanation of ".pyvisarc". * doc/homepage.txt, doc/pyvisa.tex, doc/vpp43.txt: Minor improvements * doc/pyvisa.tex, doc/vpp43.txt: Fixed little errors. 2005-06-27 Torsten Bronger * doc/pyvisa.tex: Mentioned needed Python version. * src/__init__.py: Fixed bug with missing $HOME on Windows. * setup.py: Added single module visa.py. Ignored exceptions from remove_tree() call. * doc/pyvisa.tex: Added explanation of .pyvisarc. Adjusted to new import strategy. * doc/.cvsignore: Added LaTeX intermediate outputs and logfiles. * src/.cvsignore: New file. * src/__init__.py: Added site-wide configuration file. * src/__init__.py: First usable version. * visa.py: New file. * setup.py: Substituted a native distutils routine for prune_path. * doc/Makefile: Moved creation of pyvisa.tex-related doc to /tmp/. * MANIFEST.in: Added ChnageLog and doc/Makefile. * setup.cfg: Added doc_files. * setup.py: Added symbolic link from src/doc/ to doc/. Added doc inclusion into the binary dumb distri. Untested, because supported since Python 2.4. * setup.py: Renamed package to "pyvisa". Added "make" call for making documentation. 2005-06-26 Torsten Bronger * doc/upload_homepage.sh: File deleted. * doc/Makefile: New file. * src/visa.py, src/visa_study.py: Adjusted header info. * src/pyvisa.py, src/visa.py: Renamed pyvisa.py to this file. * src/visa_study.py: Renamed visa.py to this file. * setup.py: Added code for disabling an existing local RPM configuation. Added "license" keyword parameter. * setup.cfg: New file. * doc/vpp43.txt: Added warning concerning load_library(). * doc/vpp43.txt: Added section about re-loading the VISA library. 2005-06-25 Torsten Bronger * setup.py: Improved description strings. * doc/pyvisa.tex, src/pyvisa.py: Changed default timeout for wait_for_srq() to 25 seconds. * test/test_keithley2000.py: New file. * src/vpp43.py: Removed TODO list. * .cvsignore: Added MANIFEST. * MANIFEST.in: Adjusted to current configuration. * README, readme.txt: File renamed. * misc/ctypes/Makefile, misc/ctypes/ctypes-test.c, misc/ctypes/ctypes-test.py, misc/ctypes/minimal.py, misc/ctypes/vpp43_types.py: New file. * setup.py: Added missing import. * setup.py: Adjusted to new directory structure. * src/__init__.py: New file. * src/pyvisa.py: Added copyright notice. * pyvisa.py, src/pyvisa.py, src/visa.py, src/visa_attributes.py, src/visa_exceptions.py, src/visa_messages.py, src/vpp43.py, src/vpp43_attributes.py, src/vpp43_constants.py, src/vpp43_types.py, visa.py, visa_attributes.py, visa_exceptions.py, visa_messages.py, vpp43.py, vpp43_attributes.py, vpp43_constants.py, vpp43_types.py: Moved file to src/ * ChangeLog: New file. 2005-06-23 Torsten Bronger * setup.py: Fixed too bugs. * setup.py: Brought up-to-date. 2005-06-23 Torsten Bronger * setup.py: Fixed two bugs. * setup.py: Brought up-to-date. 2005-06-22 Torsten Bronger * doc/.cvsignore: Added manual output file. * doc/upload_homepage.sh: Added PDF version. * doc/homepage.txt, doc/pyvisa.tex: First usable version. * doc/upload_homepage.sh, doc/homepage.txt: New file. * doc/vpp43.txt: Deleted the too general stuff (and moved it to homepage.txt). 2005-06-21 Torsten Bronger * doc/pyvisa.tex: Adjusted version number. Added copyright notice. * pyvisa.py: Added read_floats(). Changed test code to a more sophisticated example. * doc/pyvisa.tex: Many additions and improvements. 2005-06-20 Torsten Bronger * doc/pyvisa.tex: Many improvements and additions. * pyvisa.py: Fixed non-working wait_for_srq(). * pyvisa.py: Fixed bug in wait_for_srq(). * pyvisa.py: Added close() method. * pyvisa.py: Remove debug code. * pyvisa.py: The resource_manager is now cleanly deconstructed when the program is terminated. * pyvisa.py: Made calles in __del__ secure. * pyvisa.py: Deleted remains of SRQ handler. * pyvisa.py: Removed SRQ callback handler. * pyvisa.py: Renamed some variables. Added call to mother class in one __del__ routine. 2005-06-19 Torsten Bronger * doc/pyvisa.tex: Minor markup improvements. * doc/pyvisa.tex: Added license. Minor improvements. * doc/LICENSE: New file. * doc/pyvisa.tex: Added a lot of contents. * doc/pyvisa.tex: Added timeout options. 2005-06-18 Torsten Bronger * doc/pyvisa.tex: New file. * pyvisa.py: Deleted MAID test routines. As a constructor keyword argument, "timeout" may be None. * pyvisa.py: Removed superfluous supressions of warnings. Made "\r\n" the default term_chars for GPIB instruments. 2005-06-17 Torsten Bronger * vpp43.py: Removed doubled warnings. * vpp43.py: Removed some warnings that weren't significant enough. * pyvisa.py: Improved example. * pyvisa.py: Added timeout property. Added wait_for_srq(). * vpp43.py: Removed ViSession from return values (replaced by integers) because it's not hashable. * doc/vpp43.txt: Changed all "ViSession" to "integer". 2005-06-16 Torsten Bronger * pyvisa.py: Added use of VI_ATTR_SUPPRESS_END_EN. * vpp43.py: Fixed read_asynchronously(). * doc/vpp43.txt: Explained fixed read_asynchronously(). 2005-06-15 Torsten Bronger * pyvisa.py: Simplified SRQ handling greatly; still untested. * pyvisa.py: Very first and untested implementation of service request callbacks. * pyvisa.py: Cosmetic improvement. * pyvisa.py: Made module runnable. * pyvisa.py: Consequent tabify. Added _resources. 2005-06-14 Torsten Bronger * pyvisa.py: Added docstrings. Removed spurious "\". Improved test for GPIB instrument. * pyvisa.py: Added GpibInstrument with trigger method. Made the class Instrument more general. 2005-06-05 Torsten Bronger * pyvisa.py: Added many docstrings and comments. 2005-06-04 Torsten Bronger * pyvisa.py: Added code to wait for device to be present after having opened it. * vpp43.py: Removed "generate_warnings" 2005-06-02 Torsten Bronger * doc/vpp43.txt: Minor improvements. * vpp43.py: Fixed bug in parse_resource_extended(). * pyvisa.py: Renamed termination_characters to term_chars. Realised term_chars and timeout as keyword arguments. * pyvisa.py: Added get_instruments_list(). Added heuristics for aliases in resource names. * pyvisa.py: Moved some functionality to ResourceTemplate. * vpp43.py: Added __init__ to Singleton. * vpp43.py: Fixed wrong constructor call in singleton class. 2005-06-01 Torsten Bronger * pyvisa.py: Added Gpib class. Added a doc string. * pyvisa.py: Changed to new-style classes and inheritance structure. 2005-05-31 Torsten Bronger * pyvisa.py: Added rudimentary class "Interface". * pyvisa.py: Improved regular expression. 2005-05-30 Torsten Bronger * vpp43.py: Added generate_warnings. * pyvisa.py: New file. * vpp43.py: Minor omission in docstring fixed. 2005-05-29 Torsten Bronger * doc/vpp43.txt: Re-titled document. Added VisaIOWarning. * setup.py: Order now reflects module hierarchy. * visa_exceptions.py: Added VisaIOWarning. * vpp43.py: Deleted double message. * visa_exceptions.py: Tiny code layout improvement. * vpp43.py: Added warnings. 2005-05-29 Torsten Bronger * doc/vpp43.txt: Re-titled document. Added VisaIOWarning. * setup.py: Order now reflects module hierarchy. * visa_exceptions.py: Added VisaIOWarning. * vpp43.py: Deleted double message. * visa_exceptions.py: Tiny code layout improvement. * vpp43.py: Added warnings. 2005-05-28 Torsten Bronger * setup.py: Ordinary update. * vpp43.py: Fixed a bug and a weakness in scanf, sscanf, and queryf. 2005-05-27 Torsten Bronger * doc/vpp43.txt: Added explanations to new exception. * vpp43.py: Implemented new non-string exceptions. * visa_exceptions.py: Added UnknownHandler. Renamed VisaTypeError to TypeError. * doc/vpp43.txt: Explained the user_handle in an event handler correctly. * vpp43.py: Final implementation of install_handler. 2005-05-25 Torsten Bronger * doc/.cvsignore: Added "*.out". * doc/vpp43.txt: Explaind current version of install_handler. 2005-05-25 Torsten Bronger * doc/.cvsignore: Added "*.out". * doc/vpp43.txt: Explaind current version of install_handler. 2005-05-24 Torsten Bronger * doc/.cvsignore, vpp43_attributes.py: New file. * vpp43_types.py: ViHndlr uses the "standard" calling convention on Windows. * vpp43.py: New versions of install_handler and uninstall_handler. * doc/vpp43.txt: Described new handler installer/uninstaller. 2005-05-22 Torsten Bronger * vpp43_constants.py: Restored _to_int(), because I found a way to fix it. * vpp43_constants.py: Removed _to_int(). 2005-05-20 Torsten Bronger * doc/vpp43.txt: Added reference to NI user reference manual. Updated description of get_attribute. * vpp43.py: First usable version of get_attribute(). Deleted spurious calls to ensure_string_stype(). * vpp43.py: Fixed various bugs. First try with the get_attribute function. 2005-05-19 Torsten Bronger * doc/vpp43.txt: Moved "Diagnostics" section. Mentioned ctypes and Enthought-Python. * doc/vpp43.txt: Fixed minor errors. * doc/vpp43.txt: Added description of exceptions. * vpp43.py: Fixed a couple of issues in printf, scanf etc. parameters conversion. A couple of minor bugfixes, after code review due to writing documentation. * vpp43_types.py: Made ViBuf equal to ViString. * visa_exceptions.py: Fixed unbound name. Added VisaTypeError. 2005-05-18 Torsten Bronger * doc/vpp43.txt: Added general documentation. * doc/vpp43.txt: Spell-checked. * doc/vpp43.txt: First usable version. * doc/vpp43.txt: Added further functions. * vpp43.py: Added convert_to_byref. Minor bugfix. 2005-05-17 Torsten Bronger * doc/vpp43.txt: Implemented further routines. Added copyright notice. * vpp43.py: Fixed many bugs. Added some default values for parameters. * doc/vpp43.txt: Further work on the function descriptions. * doc/default.css: New file. * doc/vpp43.txt: Prepared a couple of function descriptions. * doc/vpp43.txt: Raw version of the function descriptions inserted. (Full of errors.) 2005-05-16 Torsten Bronger * doc/vpp43.txt: New file. * vpp43.py: Sorted all functions by alphabet. * vpp43.py: Fixed a couple of bugs. Deleted "ensure_string_argument()". 2005-05-15 Torsten Bronger * visa.py: Reverted to last version. * vpp43.py: Deleded explicit ctypes casts. * visa_exceptions.py: Bug fixed. * vpp43.py: Many serious fixes. * vpp43.py: Added ctypes argtypes (function signatures). 2005-05-14 Torsten Bronger * visa.py: Added deprecated type definitions. * vpp43.py: Improved formatting. * vpp43.py: Deleted all VPP types where not necessary (i.e., string and byte array types). 2005-05-12 Torsten Bronger * vpp43.py: ViSession(vi) --> vi. Added many comments. 2005-05-11 Torsten Bronger * vpp43.py: Minor fixes. Added local TODO list. 2005-05-09 Torsten Bronger * vpp43.py: Added correct list for check_status(). Minor corrections. * vpp43.py: All functions implemented. * vpp43.py: More functions added. 2005-05-08 Torsten Bronger * vpp43.py: Added further functions. Many corrections. Added support for cdecl in viPrintf etc with Windows. 2005-03-29 gth * visa.py: added code for event handling with callback functions, needs more work * visa_attributes.py: added class AttrBitSet, added attributes for event IO_COMPLETION * vpp43_types.py: fixed bug in definition of ViHndlr, return type was missing * setup.py: added visa_messages.py to list of files 2005-03-23 Torsten Bronger * vpp43.py: Added more functions. * vpp43.py: Added further routines. 2005-03-22 gth * visa.py, visa_attributes.py: added setattr (viSetAttribute), with string or numeric arguments 2005-03-20 Torsten Bronger * visa_messages.py: Minor changes. * visa_exceptions.py: Renamed base exception class to "Error". * vpp43.py: Added further routines. 2005-03-19 Torsten Bronger * visa_messages.py, vpp43_constants.py, vpp43_types.py: Improved code documentation. * vpp43.py: Added first wrapper routines. Changed export strategy: Instead of underscores, I now use __all__. * vpp43.py: Added some documentation. * vpp43.py: Moved excaptions to visa_exceptions.py. Added loading of VISA library. * visa_exceptions.py: New file. 2005-03-18 Torsten Bronger * vpp43.py: Added exception class and loading of library. Code is not working yet! 2005-03-18 gth * visa.py, visa_attributes.py: started adding attribute handling (viGetAttribute), incomplete * vpp43_types.py: resolved conflict (ViString) 2005-03-17 Torsten Bronger * vpp43_types.py: Added missing qualifier. * visa_messages.py: Fixed import error. 2005-03-17 gth * MANIFEST.in, readme.txt: New file. * .cvsignore: added build, dist (Python setup directories) * visa_messages.py: definition of __all__ leads to strange import error, commented out * vpp43_types.py: Changed definition of ViString, ViPString * setup.py, visa.py: New file 2005-03-17 Torsten Bronger * vpp43.py: Added some metadata and imports. 2005-03-16 Torsten Bronger * visa_messages.py: Added docstring. * vpp43_constants.py: Moves "completion_and_error_messages" to its own file. * vpp43_types.py: Added some meta data. Made ctypes import in a way that it's not re-exported again. * visa_messages.py: New file. 2005-03-15 Torsten Bronger * vpp43_constants.py: Added some comments. 2005-03-14 Torsten Bronger * vpp43_constants.py: Added attributes, events, and miscellaneous values. 2005-03-13 Torsten Bronger * vpp43_constants.py: New file. * vpp43_types.py: Added encoding declaration. * .cvsignore: New file. * vpp43.py: Moved type definitions to vpp43_types.py. Added copyright notice. Added encoding declaration. * vpp43-types.py, vpp43_types.py: File renamed. * vpp43-types.py: New file. 2005-03-12 Torsten Bronger * vpp43.py: Changed a lot to avoid exec statements. * vpp43.py, COPYING: New file. pyvisa-1.11.3/LICENSE000066400000000000000000000021261375165327600141350ustar00rootroot00000000000000The MIT License Copyright (c) 2005-2019 PyVISA Authors and contributors. See AUTHORS Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. pyvisa-1.11.3/MANIFEST.in000066400000000000000000000003111375165327600146600ustar00rootroot00000000000000include README AUTHORS CHANGES LICENSE ChangeLog recursive-include pyvisa * recursive-include docs * recursive-include examples * prune docs/build global-exclude *.pyc *~ .DS_Store *__pycache__* *.pyo pyvisa-1.11.3/README.rst000066400000000000000000000073171375165327600146260ustar00rootroot00000000000000PyVISA ====== .. image:: https://github.com/pyvisa/pyvisa/workflows/Continuous%20Integration/badge.svg :target: https://github.com/pyvisa/pyvisa/actions :alt: Continuous integration .. image:: https://github.com/pyvisa/pyvisa/workflows/Documentation%20building/badge.svg :target: https://github.com/pyvisa/pyvisa/actions :alt: Documentation building .. image:: https://dev.azure.com/pyvisa/pyvisa/_apis/build/status/pyvisa.keysight-assisted?branchName=master :target: https://dev.azure.com/pyvisa/pyvisa/_build :alt: Keysight assisted testing .. image:: https://codecov.io/gh/pyvisa/pyvisa/branch/master/graph/badge.svg :target: https://codecov.io/gh/pyvisa/pyvisa :alt: Code Coverage .. image:: https://readthedocs.org/projects/pyvisa/badge/?version=latest :target: https://pyvisa.readthedocs.io/en/latest/?badge=latest :alt: Documentation Status .. image:: https://img.shields.io/pypi/l/PyVISA :target: https://pypi.python.org/pypi/pyvisa :alt: PyPI - License .. image:: https://img.shields.io/pypi/v/PyVISA :target: https://pypi.python.org/pypi/pyvisa :alt: PyPI A Python package for support of the "Virtual Instrument Software Architecture" (VISA), in order to control measurement devices and test equipment via GPIB, RS232, Ethernet or USB. Description ----------- The programming of measurement instruments can be real pain. There are many different protocols, sent over many different interfaces and bus systems (GPIB, RS232, USB). For every programming language you want to use, you have to find libraries that support both your device and its bus system. In order to ease this unfortunate situation, the Virtual Instrument Software Architecture (VISA_) specification was defined in the middle of the 90'. Today VISA is implemented on all significant operating systems. A couple of vendors offer VISA libraries, partly with free download. These libraries work together with arbitrary peripheral devices, although they may be limited to certain interface devices, such as the vendor’s GPIB card. The VISA specification has explicit bindings to Visual Basic, C, and G (LabVIEW’s graphical language). Python can be used to call functions from a VISA shared library (`.dll`, `.so`, `.dylib`) allowing to directly leverage the standard implementations. In addition, Python can be used to directly access most bus systems used by instruments which is why one can envision to implement the VISA standard directly in Python (see the `PyVISA-Py` project for more details). PyVISA is both a Python wrapper for VISA shared libraries but can also serve as a front-end for other VISA implementation such as `PyVISA-Py`. .. _VISA: http://www.ivifoundation.org/specifications/default.aspx .. _`PyVISA-Py`: http://pyvisa-py.readthedocs.io/en/latest/ VISA and Python --------------- Python has a couple of features that make it very interesting for measurement controlling: - Python is an easy-to-learn scripting language with short development cycles. - It represents a high abstraction level [2], which perfectly blends with the abstraction level of measurement programs. - It has a very rich set of native libraries, including numerical and plotting modules for data analysis and visualisation. - A large set of books (in many languages) and on-line publications is available. Requirements ------------ - Python (tested with 3.6+) - VISA (tested with NI-VISA 17.5, Win7, from www.ni.com/visa and Keysight-VISA ) Installation -------------- Using pip: $ pip install pyvisa or easy_install: $ easy_install pyvisa or download and unzip the source distribution file and: $ python setup.py install Documentation -------------- The documentation can be read online at https://pyvisa.readthedocs.org pyvisa-1.11.3/azure-pipelines.yml000066400000000000000000000033421375165327600167700ustar00rootroot00000000000000# Python package # Create and test a Python package on multiple Python versions. # Add steps that analyze code, save the dist with the build record, publish to a PyPI-compatible index, and more: # https://docs.microsoft.com/azure/devops/pipelines/languages/python trigger: branches: include: - master - staging - trying pr: - master variables: PYVISA_KEYSIGHT_VIRTUAL_INSTR: 1 pool: name: default demands: KEYSIGHT -equals TCPIP steps: - script: | echo Activate conda call $(CONDA_PATH)\activate.bat echo Create environment conda create -n test_ python=3.7 numpy --yes displayName: 'Create environment' - script: | echo Activate conda call $(CONDA_PATH)\activate.bat echo Activate environment call conda activate test_ echo Install project pip install -e . displayName: 'Install dependencies' - script: | echo Activate conda call $(CONDA_PATH)\activate.bat echo Activate environment call conda activate test_ echo Install pytest and co pip install pytest pytest-azurepipelines pytest-cov echo Run pytest python -X dev -m pytest --pyargs pyvisa --cov pyvisa --cov-report xml -v displayName: 'Run tests' - script: | echo Activate conda call $(CONDA_PATH)\activate.bat echo Activate environment call conda activate test_ echo Install codecov pip install codecov echo Run codecov codecov --file coverage.xml --token $(CODECOV_TOKEN) --env PYVISA_KEYSIGHT_VIRTUAL_INSTR --tries 5 --required -F unittests --name codecov-umbrella displayName: 'Upload test coverage results' - script: | call $(CONDA_PATH)\activate.bat conda remove -n test_ --all --yes displayName: 'Remove test environment' condition: always() pyvisa-1.11.3/bors.toml000066400000000000000000000002171375165327600147710ustar00rootroot00000000000000status = ["Check code formatting", "Tests result", "Docs building", "pyvisa.keysight-assisted"] delete-merged-branches = true timeout_sec = 600pyvisa-1.11.3/code-of-conduct.md000066400000000000000000000064521375165327600164310ustar00rootroot00000000000000# Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies within all project spaces, and it also applies when an individual is representing the project or its community in public spaces. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at m.dartiailh@gmail.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq pyvisa-1.11.3/dev-requirements.txt000066400000000000000000000000571375165327600171710ustar00rootroot00000000000000black flake8 mypy isort sphinx sphinx-rtd-themepyvisa-1.11.3/docs/000077500000000000000000000000001375165327600140575ustar00rootroot00000000000000pyvisa-1.11.3/docs/Makefile000066400000000000000000000127001375165327600155170ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pyvisa.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pyvisa.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/pyvisa" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pyvisa" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." pyvisa-1.11.3/docs/make.bat000066400000000000000000000122521375165327600154660ustar00rootroot00000000000000@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source set I18NSPHINXOPTS=%SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. texinfo to make Texinfo files echo. gettext to make PO message catalogs echo. changes to make an overview over all changed/added/deprecated items echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\pyvisa.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\pyvisa.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "texinfo" ( %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo if errorlevel 1 exit /b 1 echo. echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. goto end ) if "%1" == "gettext" ( %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale if errorlevel 1 exit /b 1 echo. echo.Build finished. The message catalogs are in %BUILDDIR%/locale. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) :end pyvisa-1.11.3/docs/source/000077500000000000000000000000001375165327600153575ustar00rootroot00000000000000pyvisa-1.11.3/docs/source/_static/000077500000000000000000000000001375165327600170055ustar00rootroot00000000000000pyvisa-1.11.3/docs/source/_static/logo-full.jpg000066400000000000000000000252221375165327600214120ustar00rootroot00000000000000JFIFHH@ICC_PROFILE0appl mntrRGB XYZ   acspAPPLappl-appl dscmdescogXYZlwtptrXYZbXYZrTRCcprt8chad,gTRCbTRCmluc enUS&~esES&daDK.deDE,fiFI(frFU(*itIT(VnlNL(nbNO&ptBR&svSE&jaJPRkoKR@zhTWlzhCNruRU"plPL,Yleinen RGB-profiiliGenerisk RGB-profilProfil Gnrique RVBN, RGB 000000u( RGB r_icϏPerfil RGB GenricoAllgemeines RGB-Profilfn RGB cϏeNGenerel RGB-beskrivelseAlgemeen RGB-profiel| RGB \ |Profilo RGB GenericoGeneric RGB Profile1I89 ?@>D8;L RGBUniwersalny profil RGBdescGeneric RGB ProfileGeneric RGB ProfileXYZ Zus4XYZ RXYZ tM=XYZ (6curvtextCopyright 2007 Apple Inc., all rights reserved.sf32 B&lExifMM*bj(1r2iHHAdobe Photoshop CS4 Macintosh2013:08:26 20:57:27C     C  " }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?(((((((((((((((((?>0 vr_M.p5?/ShFE0<ٺ;7 #Ě'KM!I?P1_",G;In=:lw{e%$qƬd+?ioSKI ^iyyY_$XnkOyw eZns&}hE()8}gu|}x3,\lI>|H֗Jϊ[Wc,Y2Dk*|UVnRi䉃# ??\_`n\{>7sjo#Xy<c+g'@uI%ƻi4}떅ʬB_G)kM'B=~IT:(:(((((((((Ց_iz52X[b}4jH4{^^X[ZZ4~ /$0x~1|d_?/=F~q^#H ؠ*Af㠯nT䜏ˎ>ʊjֹ֓3eN+i{O~(|h}Yn-|w$D2Å8<%Ə/\xIrNɯ[U9:ౖ\GʼFRjT{4i|1SASѵ,1"δ1>ܼ8g܏TmtN}w~ֿqyY_8⠻g~A~x3[Wڋlv+6`ihcBt*:r:(` ( ( ( ( ( ( ( ( ֿa?zK?8?} _:~K?/KXV]aqNr}n _ SџfI֐<#wַ<mO? &^&_ Bff:U%&좯#Zw9%{v,6U#" ks4g"8vq?}t1Ox#?%cmk" KUS{8.vp: q]Sx[E p0ݲ1.#Sd }Z\ͫ~yg؊׳}vg??t߮8)S7Ka|\.+ >[މy:sq+'O*v;Gg&s5NY3qg3ʶ??vzX :Odz ' 'I5{t'Ҿ|SjWY_A!ʟcJu%y?6 j9EEPEPEPEPEPEPEPEP\{?x3Y5a-P}pt9EhJ->oE a)T0yiwD1>?K -{7W>ǶG h"[|%xb2{7|wc/ x Eu kwl4E'a}3Tk>25ә3.c7T%B>lgǐG9Qu[ͫk'Kt9+Yrݖ5EhZ*K[: 9ϯJcxPKǚö==է`9om*.V3@˃Аq>|-O <;gnw 1sƺ<kHUcBk\neB*O[H+q 7 S2oqඞ?.u~\5_Z01{Ud򬾖 ?.c*b3?QEEPEPEPEPEPEPEPEPEPUg]{֭Td ٬3(KiK?ķs F<5ϼ7=kWBҵ0j=j˿vpZQ&xS%&,Q4 s2 c澁6EyaxRIG2JC$( }~'0xzή-F]#l]xs6cTWލo.⋿?\k&%s"8ݜk1"!|gϦjljUo)^87Tf lY,k9\g5dwu;|~55jlhFsW!n]VҠ>M=tѱEӻ'VR\sY';L麄:^=FLyX $g߲o߈?q:]˧77S4JCIbcbNH5' qIŻ[&m cqJ?MZ+h=ew%-tb}$t 33^vU8&zJU%W=Ҋ}|o#m-3OU..aK3ʇQq99f_g,-t#nS"Oq! G @$9՞SJ:XjՔRVC6W7wQ_fo|ocj4JIDDۈs=_7>4|6GiGOE9 8\mĪ'9>kk<_6qE|/2~>:-\u_ _^heiW3 "HPgI8'%H-BI_1ң[Nu>Z=Z|w$wXgv fcyşv-/y<.|Ckʴ_-|E?h1RO \ޘ4=CNIl:>ˢ> un0KkLHh }~} .^:$*Wk? N&rX*ivO#|Iً6P]:;PoHxC. /Nf&`IP | x BQ~V嘼Mhk (ۃψ+x'FHԵ *KY2LQ!hI*ge1у}{fY0XyVGW.o[ Ũ\#U2 ;Q0XQ]{[7VL(;¼5& 5&0^?0`8:]_şw߈]Vk5)C(T?*i x+Km?I-migTE`5\SI4(u$GinUm="#Egeq֭3­gJ7e՟gxo-uAeitKyL$*2#,p{şG>6x3ִwhxգu J4M?H<6~>a!|^4T+cpΗ~͟xuׁ[MM^0a O?1_q ,NX^|}MBs_x4Jw^y>rp/ᦛvqV"Kg_ ߱gtɡh O+ \0;BG5 "EE,q"F0M_7*V[ɷAN;E$|;|ɟxk+$>/WIeG&}LĿ9\%}rsO>'5=LVmJװ*&WPDWmE|u9MK!i5C:̰[ϪXr@iiap2;p>~W_/*xD~wW uYntI,DDO8_=6|u ?|W&]n!qyLs$97͢N=UTuG?V[ž1|oxG\״giJwV⺚IQ>Ҕ] ^V 4UyntkG'OVl΄c{If̂+ 2CfI7WW4qpd\VP'+?_{ _/?EWb>&ة4U>&ة4_'2y@?6?'R{3zӥ0x#I++N8kolRr蝗|]?=_YxŖ$A[+'̒BW4Q_wl} C OlE[^e֭vF庈mg_ß$Sn+ç륧_ɽN]@~6~~~~V6۶e\gKq;dIA1 }/ Ԏ*\>s ^>vվhcgu*8e5{Za?~W^4f⛟2" H2T#xTkMō֖y2o& 9%>'6ZMm>;[XD5R,+zN旧E}fKXAr׫V*?og^- ^ŬoGuuhs/nU/c_d7QжnH@y9cNOfu=>"}cR+u8|i!d\t7 -$%\z Q>6WQF[KVn}9 +lt, j6L-\cH''6s<^U3ӂ;d#a8,w-=74|Sy7(SE&}LĿ9\%rK?`o3qUI>?jt)ş`:h0|<ަmW2u%5> ' G ? a%~/l]&Ǟiy20 A=i;KhNլ%o#捿V ] <-(1UnX{Cq޾l`1w<Dou)SX{Q6ݟ)as*(Jm??o? o(}xy`*I aXe*yh֚o_5[u-J6 2GT+3Q/i3oXX81 ,D潿uSQbj9{&8*0}ҷ~ؚW~-cĚVZho@~5:xPg\Wd㬾ro(>'*8tjzml̖KwD]@$ kqEH)?7d:9j6$p]`#ºDw]>I[i^6 )rXPI~_A9=-Qss{Y߽#ُw4w|YstFu_3DAmml23}3úekA.5GI 8Qyncө:9JإqIhZ-G )6o]Oƈ>$ֿ5Z\WnP1\0aw&ހ9qei:agaN.e%u'C_tW."TiYgSib?<<|fu<]CwGѮ$I5 WYusGo @#v(9+ំOVD" $GZh+4kcdcV=<&[r~h~Oث⏇ 77pI\%>21I+d|W}V9i[YTi[M|-m{__foz핮xᗆtۨu(.c- )Ul_8_UeylWRN=4NgSPڳ24{ Z5I#{2g/UN$d8$sZQ^cbQE ( e>> import pyvisa >>> rm = pyvisa.ResourceManager() you can access the corresponding ``VisaLibrary`` instance under the |visalib| attribute. As an example, consider the VISA function ``viMapAddress``. It appears in the low-level layer as the static method ``viMapAddress`` of |visalib| attributed and also appears in the middle-level layer as ``map_address``. You can recognize low and middle-level functions by their names. Low-level functions carry the same name as in the shared library, and they are prefixed by **vi**. Middle-level functions have a friendlier, more pythonic but still recognizable name. Typically, camelCase names where stripped from the leading **vi** and changed to underscore separated lower case names. The docs about these methods is located here :ref:`api`. Low-level ~~~~~~~~~ You can access the low-level functions directly exposed as static methods, for example:: >>> rm.visalib.viMapAddress() To call this functions you need to know the function declaration and how to interface it to python. To help you out, the ``VisaLibrary`` object also contains middle-level functions. It is very likely that you will need to access the VISA constants using these methods. You can find the information about these constants here :ref:`api_constants` Middle-level ~~~~~~~~~~~~ The ``VisaLibrary`` object exposes the middle-level functions which are one-to-one mapped from the foreign library as bound methods. Each middle-level function wraps one low-level function. In this case:: >>> rm.visalib.map_address() The calling convention and types are handled by the wrapper. pyvisa-1.11.3/docs/source/advanced/backends.rst000066400000000000000000000213371375165327600214360ustar00rootroot00000000000000.. _advanced-backends: A frontend for multiple backends ================================ .. include:: ../substitutions.sub A small historical note might help to make this section clearer. So bear with with me for a couple of lines. Originally PyVISA was a Python wrapper to the VISA library. More specifically, it was :py:mod:`ctypes` wrapper around the NI-VISA. This approach worked fine but made it difficult to develop other ways to communicate with instruments in platforms where NI-VISA was not available. Users had to change their programs to use other packages with different API. Since 1.6, PyVISA is a frontend to VISA. It provides a nice, Pythonic API and can connect to multiple backends. Each backend exposes a class derived from VisaLibraryBase that implements the low-level communication. The ctypes wrapper around IVI-VISA is the default backend (called **ivi**) and is bundled with PyVISA for simplicity. In general, IVI-VISA can be NI-VISA, Keysight VISA, R&S VISA, tekVISA etc. By default, it calls the library that is installed on your system as VISA library. You can specify the backend to use when you instantiate the resource manager using the ``@`` symbol. Remembering that **ivi** is the default, this:: >>> import pyvisa >>> rm = pyvisa.ResourceManager() is the same as this:: >>> import pyvisa >>> rm = pyvisa.ResourceManager('@ivi') You can still provide the path to the library if needed:: >>> import pyvisa >>> rm = pyvisa.ResourceManager('/path/to/lib@ivi') Under the hood, the |ResourceManager| looks for the requested backend and instantiate the VISA library that it provides. PyVISA locates backends by name. If you do: >>> import pyvisa >>> rm = pyvisa.ResourceManager('@somename') PyVISA will try to import a package/module named ``pyvisa_somename`` which should be installed in your system. This is a loosely coupled configuration free method. PyVISA does not need to know about any backend out there until you actually try to use it. You can list the installed backends by running the following code in the command line:: pyvisa-info Developing a new Backend ------------------------ What does a minimum backend looks like? Quite simple:: from pyvisa.highlevel import VisaLibraryBase class MyLibrary(VisaLibraryBase): pass WRAPPER_CLASS = MyLibrary Additionally you can provide a staticmethod named `get_debug_info` that should return a dictionary of debug information which is printed when you call ``pyvisa-info`` An important aspect of developing a backend is knowing which VisaLibraryBase method to implement and what API to expose. A **complete** implementation of a VISA Library requires a lot of functions (basically almost all level 2 functions as described in :ref:`advanced-architecture` (there is also a complete list at the bottom of this page). But a working implementation does not require all of them. As a **very minimum** set you need: - **open_default_resource_manager**: returns a session to the Default Resource Manager resource. - **open**: Opens a session to the specified resource. - **close**: Closes the specified session, event, or find list. - **list_resources**: Returns a tuple of all connected devices matching query. (you can get the signature below or here :ref:`api_visalibrarybase`) But of course you cannot do anything interesting with just this. In general you will also need: - **get_attribute**: Retrieves the state of an attribute. - **set_atribute**: Sets the state of an attribute. If you need to start sending bytes to MessageBased instruments you will require: - **read**: Reads data from device or interface synchronously. - **write**: Writes data to device or interface synchronously. For other usages or devices, you might need to implement other functions. Is really up to you and your needs. These functions should raise a :class:`pyvisa.errors.VisaIOError` or emit a :class:`pyvisa.errors.VisaIOWarning` if necessary, and store error code on a per session basis. This can be done easily by calling :py:meth:`~pyvisa.highlevel.VisaLibraryBase.handle_return_value` with the session and return value. Complete list of level 2 functions to implement:: def read_memory(self, session, space, offset, width, extended=False): def write_memory(self, session, space, offset, data, width, extended=False): def move_in(self, session, space, offset, length, width, extended=False): def move_out(self, session, space, offset, length, data, width, extended=False): def peek(self, session, address, width): def poke(self, session, address, width, data): def assert_interrupt_signal(self, session, mode, status_id): def assert_trigger(self, session, protocol): def assert_utility_signal(self, session, line): def buffer_read(self, session, count): def buffer_write(self, session, data): def clear(self, session): def close(self, session): def disable_event(self, session, event_type, mechanism): def discard_events(self, session, event_type, mechanism): def enable_event(self, session, event_type, mechanism, context=None): def flush(self, session, mask): def get_attribute(self, session, attribute): def gpib_command(self, session, data): def gpib_control_atn(self, session, mode): def gpib_control_ren(self, session, mode): def gpib_pass_control(self, session, primary_address, secondary_address): def gpib_send_ifc(self, session): def in_8(self, session, space, offset, extended=False): def in_16(self, session, space, offset, extended=False): def in_32(self, session, space, offset, extended=False): def in_64(self, session, space, offset, extended=False): def install_handler(self, session, event_type, handler, user_handle): def list_resources(self, session, query='?*::INSTR'): def lock(self, session, lock_type, timeout, requested_key=None): def map_address(self, session, map_space, map_base, map_size, def map_trigger(self, session, trigger_source, trigger_destination, mode): def memory_allocation(self, session, size, extended=False): def memory_free(self, session, offset, extended=False): def move(self, session, source_space, source_offset, source_width, destination_space, def move_asynchronously(self, session, source_space, source_offset, source_width, def move_in_8(self, session, space, offset, length, extended=False): def move_in_16(self, session, space, offset, length, extended=False): def move_in_32(self, session, space, offset, length, extended=False): def move_in_64(self, session, space, offset, length, extended=False): def move_out_8(self, session, space, offset, length, data, extended=False): def move_out_16(self, session, space, offset, length, data, extended=False): def move_out_32(self, session, space, offset, length, data, extended=False): def move_out_64(self, session, space, offset, length, data, extended=False): def open(self, session, resource_name, def open_default_resource_manager(self): def out_8(self, session, space, offset, data, extended=False): def out_16(self, session, space, offset, data, extended=False): def out_32(self, session, space, offset, data, extended=False): def out_64(self, session, space, offset, data, extended=False): def parse_resource(self, session, resource_name): def parse_resource_extended(self, session, resource_name): def peek_8(self, session, address): def peek_16(self, session, address): def peek_32(self, session, address): def peek_64(self, session, address): def poke_8(self, session, address, data): def poke_16(self, session, address, data): def poke_32(self, session, address, data): def poke_64(self, session, address, data): def read(self, session, count): def read_asynchronously(self, session, count): def read_stb(self, session): def read_to_file(self, session, filename, count): def set_attribute(self, session, attribute, attribute_state): def set_buffer(self, session, mask, size): def status_description(self, session, status): def terminate(self, session, degree, job_id): def uninstall_handler(self, session, event_type, handler, user_handle=None): def unlock(self, session): def unmap_address(self, session): def unmap_trigger(self, session, trigger_source, trigger_destination): def usb_control_in(self, session, request_type_bitmap_field, request_id, request_value, def usb_control_out(self, session, request_type_bitmap_field, request_id, request_value, def vxi_command_query(self, session, mode, command): def wait_on_event(self, session, in_event_type, timeout): def write(self, session, data): def write_asynchronously(self, session, data): def write_from_file(self, session, filename, count): pyvisa-1.11.3/docs/source/advanced/continuous_integration.rst000066400000000000000000000036451375165327600244770ustar00rootroot00000000000000.. _advanced-cis: Continuous integration setup ============================ Testing PyVISA in a thorough manner is challenging due to the need to access both a VISA library implementation and actual instruments to test against. In their absence, tests are mostly limited to utility functions and infrastructure. Those limited tests are found at the root of the testsuite package of pyvisa. They are run, along with linters and documentation building on each commit using Github Actions. Thanks to Keysight tools provided to PyVISA developers, it is also possible to test most capabilities of message based resources. However due to the hardware requirements for the build bots, those tests cannot be set up on conventional hosted CIs platform such as Travis, Azure, Github actions, etc. Self-hosted builder can be used to run the tests requiring those tools. PyVISA developer have chosen to use Azure Pipelines to run self-hosted runners. This choice was based on the ease of use of Azure and the expected low maintenance the builder should require since the CIs proper is handled through Azure. Github Actions has also been considered but due to security reason, self-hosted runners should not run on forks and Github Actions does not currently provide a way to forbid running self-hosted runners on forks. An Azure self-hosted runner has been set in place and will remain active till December 2020. This runner can only test TCPIP based resources. A new runner will be set up in the first trimester of 2021 with hopefully capabilities extended to USB::INSTR and GPIB resources. The setup of the current runner is not perfect and the runner may go offline at times. If this happen, before December 2020, please contact @MatthieuDartiailh on Github. .. note:: The current runner runs on Windows and uses conda. Due to the working of the activation scripts on Windows calls to `activate` or `conda activate` must be preceded by `call`. pyvisa-1.11.3/docs/source/advanced/index.rst000066400000000000000000000004341375165327600207660ustar00rootroot00000000000000.. _advanced: Advanced topics =============== This section of the documentation will cover the internal details of PyVISA. In particular, it will explain in details how PyVISA manage backends. .. toctree:: :maxdepth: 2 architecture backends continuous_integration pyvisa-1.11.3/docs/source/api/000077500000000000000000000000001375165327600161305ustar00rootroot00000000000000pyvisa-1.11.3/docs/source/api/constants.rst000066400000000000000000000013111375165327600206720ustar00rootroot00000000000000.. _api_constants: Constants module ---------------- .. py:module:: pyvisa.constants Provides user-friendly naming to values used in different functions. .. autoclass:: AccessModes :members: :undoc-members: .. autoclass:: StopBits :members: :undoc-members: .. autoclass:: Parity :members: :undoc-members: .. autoclass:: SerialTermination :members: :undoc-members: .. autoclass:: InterfaceType :members: :undoc-members: .. autoclass:: AddressState :members: :undoc-members: .. autoclass:: IOProtocol :members: :undoc-members: .. autoclass:: LineState :members: :undoc-members: .. autoclass:: StatusCode :members: :undoc-members: pyvisa-1.11.3/docs/source/api/index.rst000066400000000000000000000001731375165327600177720ustar00rootroot00000000000000.. _api: === API === .. toctree:: :maxdepth: 1 visalibrarybase resourcemanager resources constants pyvisa-1.11.3/docs/source/api/resourcemanager.rst000066400000000000000000000004341375165327600220450ustar00rootroot00000000000000.. _api_resourcemanager: Resource Manager ---------------- .. autoclass:: pyvisa.highlevel.ResourceInfo .. autoclass:: pyvisa.highlevel.ResourceManager :members: close, session, list_resources, list_resources_info, resource_info, open_bare_resource, open_resource, last_status pyvisa-1.11.3/docs/source/api/resources.rst000066400000000000000000000067561375165327600207120ustar00rootroot00000000000000.. _api_resources: Resource classes ---------------- Resources are high level abstractions to managing specific sessions. An instance of one of these classes is returned by the :meth:`~pyvisa.highlevel.ResourceManager.open_resource` depending on the resource type. Generic classes ~~~~~~~~~~~~~~~ - :class:`~pyvisa.resources.Resource` - :class:`~pyvisa.resources.MessageBasedResource` - :class:`~pyvisa.resources.RegisterBasedResource` Specific Classes ~~~~~~~~~~~~~~~~ - :class:`~pyvisa.resources.SerialInstrument` - :class:`~pyvisa.resources.TCPIPInstrument` - :class:`~pyvisa.resources.TCPIPSocket` - :class:`~pyvisa.resources.USBInstrument` - :class:`~pyvisa.resources.USBRaw` - :class:`~pyvisa.resources.GPIBInstrument` - :class:`~pyvisa.resources.GPIBInterface` - :class:`~pyvisa.resources.FirewireInstrument` - :class:`~pyvisa.resources.PXIInstrument` - :class:`~pyvisa.resources.PXIInstrument` - :class:`~pyvisa.resources.VXIInstrument` - :class:`~pyvisa.resources.VXIMemory` - :class:`~pyvisa.resources.VXIBackplane` .. currentmodule::`pyvisa.resources` .. autoclass:: pyvisa.resources.Resource :members: :inherited-members: :undoc-members: .. autoclass:: pyvisa.resources.MessageBasedResource :members: :inherited-members: :exclude-members: ask_delay, ask_for_values, ask :undoc-members: .. autoclass:: pyvisa.resources.RegisterBasedResource :members: :inherited-members: :undoc-members: .. autoclass:: pyvisa.resources.SerialInstrument :members: :inherited-members: :exclude-members: ask_delay, ask_for_values, ask :undoc-members: .. autoclass:: pyvisa.resources.TCPIPInstrument :members: :inherited-members: :exclude-members: ask_delay, ask_for_values, ask :undoc-members: .. autoclass:: pyvisa.resources.TCPIPSocket :members: :inherited-members: :exclude-members: ask_delay, ask_for_values, ask :undoc-members: .. autoclass:: pyvisa.resources.USBInstrument :members: :inherited-members: :exclude-members: ask_delay, ask_for_values, ask :undoc-members: .. autoclass:: pyvisa.resources.USBRaw :members: :inherited-members: :exclude-members: ask_delay, ask_for_values, ask :undoc-members: .. autoclass:: pyvisa.resources.GPIBInstrument :members: :inherited-members: :exclude-members: ask_delay, ask_for_values, ask :undoc-members: .. autoclass:: pyvisa.resources.GPIBInterface :members: :inherited-members: :exclude-members: ask_delay, ask_for_values, ask :undoc-members: .. autoclass:: pyvisa.resources.FirewireInstrument :members: :inherited-members: :exclude-members: ask_delay, ask_for_values, ask :undoc-members: .. autoclass:: pyvisa.resources.PXIInstrument :members: :inherited-members: :exclude-members: ask_delay, ask_for_values, ask :undoc-members: .. autoclass:: pyvisa.resources.PXIMemory :members: :inherited-members: :exclude-members: ask_delay, ask_for_values, ask :undoc-members: .. autoclass:: pyvisa.resources.VXIInstrument :members: :inherited-members: :exclude-members: ask_delay, ask_for_values, ask :undoc-members: .. autoclass:: pyvisa.resources.VXIMemory :members: :inherited-members: :exclude-members: ask_delay, ask_for_values, ask :undoc-members: .. autoclass:: pyvisa.resources.VXIBackplane :members: :inherited-members: :exclude-members: ask_delay, ask_for_values, ask :undoc-members: pyvisa-1.11.3/docs/source/api/visalibrarybase.rst000066400000000000000000000001651375165327600220460ustar00rootroot00000000000000.. _api_visalibrarybase: Visa Library ------------ .. autoclass:: pyvisa.highlevel.VisaLibraryBase :members: pyvisa-1.11.3/docs/source/conf.py000066400000000000000000000231541375165327600166630ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # PyVISA documentation build configuration file # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import datetime import os import sys if sys.version_info >= (3, 8): from importlib.metadata import version as get_version else: from importlib_metadata import version as get_version # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. needs_sphinx = "1.8" # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ "sphinx.ext.autodoc", "sphinx.ext.doctest", "sphinx.ext.intersphinx", "sphinx.ext.coverage", "sphinx.ext.viewcode", "sphinx.ext.mathjax", "sphinx.ext.napoleon", ] # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] # The suffix of source filenames. source_suffix = ".rst" # The encoding of source files. # source_encoding = 'utf-8-sig' # The master toctree document. master_doc = "index" # General information about the project. project = "PyVISA" author = "PyVISA Authors" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. version = get_version(project) release = version this_year = datetime.date.today().year copyright = "%s, %s" % (this_year, author) # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: # today = '' # Else, today_fmt is used as the format for a strftime call. # today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = [] # The reST default role (used for this markup: `text`) to use for all documents. # default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. # add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). # add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = 'default' html_theme = "sphinx_rtd_theme" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". # html_title = None # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. # html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ["_static"] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. # html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. # html_use_smartypants = True # Custom sidebar templates, maps document names to template names. # html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. # html_additional_pages = {} # If false, no module index is generated. # html_domain_indices = True # If false, no index is generated. # html_use_index = True # If true, the index is split into individual pages for each letter. # html_split_index = False # If true, links to the reST sources are added to the pages. # html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. # html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. # html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. # html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). # html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = "pyvisatdoc" # -- Options for LaTeX output -------------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ("index", "pyvisa.tex", "PyVISA Documentation", "PyVISA Authors", "manual"), ] # The name of an image file (relative to this directory) to place at the top of # the title page. # latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. # latex_use_parts = False # If true, show page references after internal links. # latex_show_pagerefs = False # If true, show URL addresses after external links. # latex_show_urls = False # Documents to append as an appendix to all manuals. # latex_appendices = [] # If false, no module index is generated. # latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [("index", "pyvisa", "PyVISA Documentation", ["PyVISA Authors"], 1)] # If true, show URL addresses after external links. # man_show_urls = False # -- Options for Texinfo output ------------------------------------------------ # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ( "index", "PyVISA", "PyVISA Documentation", "PyVISA Authors", "PyVISA", "One line description of project.", "Miscellaneous", ), ] # Documents to append as an appendix to all manuals. # texinfo_appendices = [] # If false, no module index is generated. # texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. # texinfo_show_urls = 'footnote' # -- Options for Epub output --------------------------------------------------- # Bibliographic Dublin Core info. epub_title = project epub_author = author epub_publisher = author epub_copyright = copyright # The language of the text. It defaults to the language option # or en if the language is not set. # epub_language = '' # The scheme of the identifier. Typical schemes are ISBN or URL. # epub_scheme = '' # The unique identifier of the text. This can be a ISBN number # or the project homepage. # epub_identifier = '' # A unique identification for the text. # epub_uid = '' # A tuple containing the cover image and cover page html template filenames. # epub_cover = () # HTML files that should be inserted before the pages created by sphinx. # The format is a list of tuples containing the path and title. # epub_pre_files = [] # HTML files shat should be inserted after the pages created by sphinx. # The format is a list of tuples containing the path and title. # epub_post_files = [] # A list of files that should not be packed into the epub file. # epub_exclude_files = [] # The depth of the table of contents in toc.ncx. # epub_tocdepth = 3 # Allow duplicate toc entries. # epub_tocdup = True # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {"python": ("http://docs.python.org/3", None)} pyvisa-1.11.3/docs/source/faq/000077500000000000000000000000001375165327600161265ustar00rootroot00000000000000pyvisa-1.11.3/docs/source/faq/contributing.rst000066400000000000000000000066141375165327600213760ustar00rootroot00000000000000.. _faq-contributing: Contributing to PyVISA ====================== You can contribute in different ways: Report issues ------------- You can report any issues with the package, the documentation to the PyVISA `issue tracker`_. Also feel free to submit feature requests, comments or questions. In some cases, platform specific information is required. If you think this is the case, run the following command and paste the output into the issue:: pyvisa-info It is useful that you also provide the log output. To obtain it, add the following lines to your code:: import pyvisa pyvisa.log_to_screen() If your issue concern a specific instrument please be sure to indicate the manufacturer and the model. Contribute code --------------- To contribute fixes, code or documentation to PyVISA, send us a patch, or fork PyVISA in github_ and submit the changes using a pull request. You can also get the code from PyPI_ or GitHub_. You can clone the public repository:: $ git clone git://github.com/pyvisa/pyvisa.git Once you have a copy of the source, you can embed it in your Python package, or install it in develop mode easily:: $ python setup.py develop Installing in development mode means that any change you make will be immediately reflected when you run pyvisa. PyVISA uses a number of tools to ensure a consistent code style and quality. The code is checked as part of the CIs system but you may want to run those locally before submitting a patch. You have multiple options to do so: - You can install `pre-commit` (using pip for example) and run:: $pre-commit install This will run all the above mentioned tools run when you commit your changes. - Install and run each tool independently. You can install all of them using pip and the `dev_requirements.txt` file. You can a look at the CIs configurations (in .github/workflows/ci.yml). Thoses tools are: - black: Code formatting - isort: Import sorting - flake8: Code quality - mypy: Typing Finally if editing docstring, please note that PyVISA uses Numpy style docstring. In order to build the documentation you will need to install `sphinx` and `sphinx_rtd_theme`. Both are listed in `dev_requirements.txt`. .. note:: If you have an old system installation of Python and you don't want to mess with it, you can try `Anaconda`_. It is a free Python distribution by Continuum Analytics that includes many scientific packages. Contributing to an existing backend ----------------------------------- Backends are the central piece of PyVISA as they provide the low level communication over the different interfaces. There a couple of backends in the wild which can use your help. Look them up in PyPI_ (try `pyvisa` in the search box) and see where you can help. Contributing a new backend -------------------------- If you think there is a new way that low level communication can be achieved, go for it. You can use any of the existing backends as a template or start a thread in the `issue tracker`_ and we will be happy to help you. .. _easy_install: http://pypi.python.org/pypi/setuptools .. _Python: http://www.python.org/ .. _pip: http://www.pip-installer.org/ .. _`Anaconda`: https://www.anaconda.com/distribution/ .. _PyPI: https://pypi.python.org/pypi/PyVISA .. _`National Instruments's VISA`: http://ni.com/visa/ .. _github: http://github.com/pyvisa/pyvisa .. _`issue tracker`: https://github.com/pyvisa/pyvisa/issues pyvisa-1.11.3/docs/source/faq/faq.rst000066400000000000000000000164411375165327600174350ustar00rootroot00000000000000.. _faq-faq: Miscellaneous questions ======================= Is *PyVISA* endorsed by National Instruments? --------------------------------------------- No. *PyVISA* is developed independently of National Instrument as a wrapper for the VISA library. Who makes *PyVISA*? ------------------- PyVISA was originally programmed by Torsten Bronger and Gregor Thalhammer. It is based on earlier experiences by Thalhammer. It was maintained from March 2012 to August 2013 by Florian Bauer. It was maintained from August 2013 to December 2017 by Hernan E. Grecco . It is currently maintained by Matthieu Dartiailh Take a look at AUTHORS_ for more information Is PyVISA thread-safe? ---------------------- Yes, PyVISA is thread safe starting from version 1.6. I have an error in my program and I am having trouble to fix it --------------------------------------------------------------- PyVISA provides useful logs of all operations. Add the following commands to your program and run it again:: import pyvisa pyvisa.log_to_screen() I found a bug, how can I report it? ----------------------------------- Please report it on the `Issue Tracker`_, including operating system, python version and library version. In addition you might add supporting information by pasting the output of this command:: pyvisa-info Error: Image not found ---------------------- This error occurs when you have provided an invalid path for the VISA library. Check that the path provided to the constructor or in the configuration file Error: Could not found VISA library ----------------------------------- This error occurs when you have not provided a path for the VISA library and PyVISA is not able to find it for you. You can solve it by providing the library path to the ``VisaLibrary`` or ``ResourceManager`` constructor:: >>> visalib = VisaLibrary('/path/to/library') or:: >>> rm = ResourceManager('Path to library') or creating a configuration file as described in :ref:`intro-configuring`. Error: `visa` module has no attribute `ResourceManager` ------------------------------------------------------- The https://github.com/visa-sdk/visa-python provides a visa package that can conflict with :py:mod:`visa` module provided by PyVISA, which is why the :py:mod:`visa` module is deprecated and it is preferred to import :py:mod:`pyvisa` instead of :py:mod:`visa`. Both modules provides the same interface and no other changes should be needed. Error: No matching architecture ------------------------------- This error occurs when you the Python architecture does not match the VISA architecture. .. note:: PyVISA tries to parse the error from the underlying foreign function library to provide a more useful error message. If it does not succeed, it shows the original one. In Mac OS X the original error message looks like this:: OSError: dlopen(/Library/Frameworks/visa.framework/visa, 6): no suitable image found. Did find: /Library/Frameworks/visa.framework/visa: no matching architecture in universal wrapper /Library/Frameworks/visa.framework/visa: no matching architecture in universal wrapper In Linux the original error message looks like this:: OSError: Could not open VISA library: Error while accessing /usr/local/vxipnp/linux/bin/libvisa.so.7:/usr/local/vxipnp/linux/bin/libvisa.so.7: wrong ELF class: ELFCLASS32 First, determine the details of your installation with the help of the following debug command:: pyvisa-info You will see the 'bitness' of the Python interpreter and at the end you will see the list of VISA libraries that PyVISA was able to find. The solution is to: 1. Install and use a VISA library matching your Python 'bitness' Download and install it from **National Instruments's VISA**. Run the debug command again to see if the new library was found by PyVISA. If not, create a configuration file as described in :ref:`intro-configuring`. If there is no VISA library with the correct bitness available, try solution 2. or 2. Install and use a Python matching your VISA library 'bitness' In Windows and Linux: Download and install Python with the matching bitness. Run your script again using the new Python In Mac OS X, Python is usually delivered as universal binary (32 and 64 bits). You can run it in 32 bit by running:: arch -i386 python myscript.py or in 64 bits by running:: arch -x86_64 python myscript.py You can create an alias by adding the following line alias python32="arch -i386 python" into your .bashrc or .profile or ~/.bash_profile (or whatever file depending on which shell you are using.) You can also create a `virtual environment`_ for this. OSError: Could not open VISA library: function 'viOpen' not found ----------------------------------------------------------------- Starting with Python 3.8, the .dll load behavior has changed on Windows (see `https://docs.python.org/3/whatsnew/3.8.html#bpo-36085-whatsnew`_). This causes some versions of Keysight VISA to fail to load because it cannot find its .dll dependencies. You can solve it by creating a configuration file and setting `dll_extra_paths` as described in :ref:`intro-configuring`. VisaIOError: VI_ERROR_SYSTEM_ERROR: Unknown system error: --------------------------------------------------------- If you have an issue creating a pyvisa.ResourceManager object, first enable screen logging (pyvisa.log_to_screen()) to ensure it is correctly finding the dll files. If it is correctly finding the dlls, you may see an error similar to: * viOpenDefaultRM('',) -> -1073807360 This issue was resolved by reinstalling python. It seems that something within the ctypes may have been corrupted. [https://github.com/pyvisa/pyvisa/issues/538] Where can I get more information about VISA? -------------------------------------------- * The original VISA docs: - `VISA specification`_ (scroll down to the end) - `VISA library specification`_ - `VISA specification for textual languages`_ * The very good VISA manuals from `National Instruments's VISA`_: - `NI-VISA User Manual`_ - `NI-VISA Programmer Reference Manual`_ - `NI-VISA help file`_ in HTML .. _`VISA specification`: http://www.ivifoundation.org/Downloads/Specifications.htm .. _`VISA library specification`: http://www.ivifoundation.org/Downloads/Class%20Specifications/vpp43.doc .. _`VISA specification for textual languages`: http://www.ivifoundation.org/Downloads/Class%20Specifications/vpp432.doc .. _`National Instruments's VISA`: http://ni.com/visa/ .. _`NI-VISA Programmer Reference Manual`: http://digital.ni.com/manuals.nsf/websearch/87E52268CF9ACCEE86256D0F006E860D .. _`NI-VISA help file`: http://digital.ni.com/manuals.nsf/websearch/21992F3750B967ED86256F47007B00B3 .. _`NI-VISA User Manual`: http://digital.ni.com/manuals.nsf/websearch/266526277DFF74F786256ADC0065C50C .. _`AUTHORS`: https://github.com/pyvisa/pyvisa/blob/master/AUTHORS .. _`Issue Tracker`: https://github.com/pyvisa/pyvisa/issues .. _`virtual environment`: http://www.virtualenv.org/en/latest/ .. _`https://docs.python.org/3/whatsnew/3.8.html#bpo-36085-whatsnew`: https://docs.python.org/3/whatsnew/3.8.html#bpo-36085-whatsnew pyvisa-1.11.3/docs/source/faq/getting_nivisa.rst000066400000000000000000000046241375165327600217000ustar00rootroot00000000000000.. _faq-getting-nivisa: NI-VISA Installation ==================== In every OS, the NI-VISA library bitness (i.e. 32- or 64-bit) has to match the Python bitness. So first you need to install a NI-VISA that works with your OS and then choose the Python version matching the installed NI-VISA bitness. PyVISA includes a debugging command to help you troubleshoot this (and other things):: pyvisa-info According to National Instruments, NI VISA **17.5** is available for the following platforms. .. note:: If NI-VISA is not available for your system, take a look at the :ref:`faq`. Mac OS X -------- Download `NI-VISA for Mac OS X`_ Supports: - Mac OS X 10.7.x x86 and x86-64 - Mac OS X 10.8.x *64-bit VISA applications are supported for a limited set of instrumentation buses. The supported buses are ENET-Serial, USB, and TCPIP. Logging VISA operations in NI I/O Trace from 64-bit VISA applications is not supported.* Windows ------- Download `NI-VISA for Windows`_ Suports: - Windows Server 2003 R2 (32-bit version only) - Windows Server 2008 R2 (64-bit version only) - Windows 8 x64 Edition (64-bit version) - Windows 8 (32-bit version) - Windows 7 x64 Edition (64-bit version) - Windows 7 (32-bit version) - Windows Vista x64 Edition (64-bit version) - Windows Vista (32-bit version) - Windows XP Service Pack 3 *Support for Windows Server 2003 R2 may require disabling physical address extensions (PAE).* Linux ----- Download `NI-VISA for Linux`_ Supports: - openSUSE 12.2 - openSUSE 12.1 - Red Hat Enterprise Linux Desktop + Workstation 6 - Red Hat Enterprise Linux Desktop + Workstation 5 - Scientific Linux 6.x - Scientific Linux 5.x More details details can be found in the `README`_ of the installer. .. note:: NI-VISA runs on other linux distros but the installation is more cumbersome. On Arch linux and related distributions, the AUR package `ni-visa`_ (early development) is known to work for the USB and TCPIP interfaces. Please note that you should restart after the installation for things to work properly. .. _`README`: http://download.ni.com/support/softlib//visa/NI-VISA/17.0/Linux/README.txt .. _`ni-visa`: https://aur.archlinux.org/packages/ni-visa/ .. _`NI-VISA for Mac OS X`: http://www.ni.com/download/ni-visa-17.5/7224/en/ .. _`NI-VISA for Windows`: http://www.ni.com/download/ni-visa-17.5/7220/en/ .. _`NI-VISA for Linux`: http://www.ni.com/download/ni-visa-17.0/6700/en/ pyvisa-1.11.3/docs/source/faq/index.rst000066400000000000000000000005221375165327600177660ustar00rootroot00000000000000.. _faq: Frequently asked questions =========================== This section covers frequently asked questions in relation with PyVISA. You will find first miscellaneous questions and next a set of questions that requires more in depth answers. .. toctree:: :maxdepth: 2 faq getting_nivisa migrating contributing pyvisa-1.11.3/docs/source/faq/migrating.rst000066400000000000000000000236541375165327600206530ustar00rootroot00000000000000.. _faq-migrating: Migrating from PyVISA < 1.5 =========================== .. note:: if you want PyVISA 1.4 compatibility use PyVISA 1.5 that provides Python 3 support, better visa library detection heuristics, Windows, Linux and OS X support, and no singleton object. PyVISA 1.6+ introduces a few compatibility breaks. Some of these decisions were inspired by the ``visalib`` package as a part of Lantz_ Short summary ------------- PyVISA 1.5 has full compatibility with previous versions of PyVISA using the legacy module (changing some of the underlying implementation). But you are encouraged to do a few things differently if you want to keep up with the latest developments and be compatible with PyVISA > 1.5. Indeed PyVISA 1.6 breaks compatibility to bring across a few good things. **If you are doing:** >>> import pyvisa >>> keithley = pyvisa.instrument("GPIB::12") >>> print(keithley.ask("*IDN?")) change it to: >>> import pyvisa >>> rm = pyvisa.ResourceManager() >>> keithley = rm.open_resource("GPIB::12") >>> print(keithley.query("*IDN?")) **If you are doing:** >>> print(pyvisa.get_instruments_list()) change it to: >>> print(rm.list_resources()) **If you are doing:** >>> import pyvisa.vpp43 as vpp43 >>> vpp43.visa_library.load_library("/path/to/my/libvisa.so.7") change it to: >>> import pyvisa >>> rm = pyvisa.ResourceManager("/path/to/my/libvisa.so.7") >>> lib = rm.visalib **If you are doing::** >>> vpp43.lock(session) change it to:: >>> lib.lock(session) or better: >>> resource.lock() **If you are doing::** >>> inst.term_chars = '\r' change it to:: >>> inst.read_termination = '\r' >>> inst.write_termination = '\r' **If you are doing::** >>> print(lib.status) change it to:: >>> print(lib.last_status) or even better, do it per resource:: >>> print(rm.last_status) # for the resource manager >>> print(inst.last_status) # for a specific instrument **If you are doing::** >>> inst.timeout = 1 # Seconds change it to:: >>> inst.timeout = 1000 # Milliseconds As you see, most of the code shown above is making a few things explict. It adds 1 line of code (instantiating the ResourceManager object) which is not a big deal but it makes things cleaner. If you were using ``printf``, ``queryf``, ``scanf``, ``sprintf`` or ``sscanf`` of ``vpp43``, rewrite as pure Python code (see below). If you were using ``Instrument.delay``, change your code or use ``Instrument.query_delay`` (see below). A few alias has been created to ease the transition: - ask -> query - ask_delay -> query_delay - get_instrument -> open_resource A more detailed description --------------------------- Dropped support for string related functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The VISA library includes functions to search and manipulate strings such as ``printf``, ``queryf``, ``scanf``, ``sprintf`` and ``sscanf``. This makes sense as VISA involves a lot of string handling operations. The original PyVISA implementation wrapped these functions. But these operations are easily expressed in pure python and therefore were rarely used. PyVISA 1.5 keeps these functions for backwards compatibility but they are removed in 1.6. We suggest that you replace such functions by a pure Python version. Isolated low-level wrapping module ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In the original PyVISA implementation, the low level implementation (``vpp43``) was mixed with higher level constructs. The VISA library was wrapped using ctypes. In 1.5, we refactored it as ``ctwrapper``. This allows us to test the foreign function calls by isolating them from higher level abstractions. More importantly, it also allows us to build new low level modules that can be used as drop in replacements for ``ctwrapper`` in high level modules. In 1.6, we made the ``ResourceManager`` the object exposed to the user. The type of the ``VisaLibrary`` can selected depending of the ``library_path`` and obtained from a plugin package. We have two of such packages planned: - a Mock module that allows you to test a PyVISA program even if you do not have VISA installed. - a CFFI based wrapper. CFFI is new python package that allows easier and more robust wrapping of foreign libraries. It might be part of Python in the future. PyVISA 1.5 keeps ``vpp43`` in the legacy subpackage (reimplemented on top of ``ctwrapper``) to help with the migration. This module is gone in 1.6. All functions that were present in ``vpp43`` are now present in ``ctwrapper`` but they take an additional first parameter: the foreign library wrapper. We suggest that you replace ``vpp43`` by accessing the ``VisaLibrary`` object under the attribute visalib of the resource manager which provides all foreign functions as bound methods (see below). No singleton objects ~~~~~~~~~~~~~~~~~~~~ The original PyVISA implementation relied on a singleton, global objects for the library wrapper (named ``visa_library``, an instance of the old ``pyvisa.vpp43.VisaLibrary``) and the resource manager (named ``resource_manager``, and instance of the old ``pyvisa.visa.ResourceManager``). These were instantiated on import and the user could rebind to a different library using the ``load_library`` method. Calling this method however did not affect ``resource_manager`` and might lead to an inconsistent state. There were additionally a few global structures such a ``status`` which stored the last status returned by the library and the warning context to prevent unwanted warnings. In 1.5, there is a new ``VisaLibrary`` class and a new ``ResourceManager`` class (they are both in ``pyvisa.highlevel``). The new classes are not singletons, at least not in the strict sense. Multiple instances of ``VisaLibrary`` and ``ResourceManager`` are possible, but only if they refer to different foreign libraries. In code, this means: >>> lib1 = pyvisa.VisaLibrary("/path/to/my/libvisa.so.7") >>> lib2 = pyvisa.VisaLibrary("/path/to/my/libvisa.so.7") >>> lib3 = pyvisa.VisaLibrary("/path/to/my/libvisa.so.8") >>> lib1 is lib2 True >>> lib1 is lib3 False Most of the time, you will not need access to a ``VisaLibrary`` object but to a ``ResourceManager``. You can do: >>> lib = pyvisa.VisaLibrary("/path/to/my/libvisa.so.7") >>> rm = lib.resource_manager or equivalently: >>> rm = pyvisa.ResourceManager("/path/to/my/libvisa.so.7") .. note:: If the path for the library is not given, the path is obtained from the user settings file (if exists) or guessed from the OS. In 1.6, the state returned by the library is stored per resource. Additionally, warnings can be silenced by resource as well. You can access with the ``last_status`` property. All together, these changes makes PyVISA thread safe. VisaLibrary methods as way to call Visa functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In the original PyVISA implementation, the ``VisaLibrary`` class was just having a reference to the ctypes library and a few functions. In 1.5, we introduced a new ``VisaLibrary`` class (``pyvisa.highlevel``) which has every single low level function defined in ``ctwrapper`` as bound methods. In code, this means that you can do:: >>> import pyvisa >>> rm = pyvisa.ResourceManager("/path/to/my/libvisa.so.7") >>> lib = rm.visalib >>> print(lib.read_stb(session)) (But it is very likely that you do not have to do it as the resource should have the function you need) It also has every single VISA foreign function in the underlying library as static method. In code, this means that you can do:: >>> status = ctypes.c_ushort() >>> ret lib.viReadSTB(session, ctypes.byref(status)) >>> print(ret.value) Ask vs. query ~~~~~~~~~~~~~ Historically, the method ``ask`` has been used in PyVISA to do a ``write`` followed by a ``read``. But in many other programs this operation is called ``query``. Thereby we have decided to switch the name, keeping an alias to help with the transition. However, ``ask_for_values`` has not been aliased to ``query_values`` because the API is different. ``ask_for_values`` still uses the old formatting API which is limited and broken. We suggest that you migrate everything to ``query_values`` Seconds to milliseconds ~~~~~~~~~~~~~~~~~~~~~~~ The timeout is now in milliseconds (not in seconds as it was before). The reason behind this change is to make it coherent with all other VISA implementations out there. The C-API, LabVIEW, .NET: all use milliseconds. Using the same units not only makes it easy to migrate to PyVISA but also allows to profit from all other VISA docs out there without extra cognitive effort. Removal of Instrument.delay and added Instrument.query_delay ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In the original PyVISA implementation, ``Instrument`` takes a ``delay`` argument that adds a pause after each write operation (This also can be changed using the ``delay`` attribute). In PyVISA 1.6, ``delay`` is removed. Delays after write operations must be added to the application code. Instead, a new attribute and argument ``query_delay`` is available. This allows you to pause between ``write` and ``read`` operations inside ``query``. Additionally, ``query`` takes an optional argument called ``query`` allowing you to change it for each method call. Deprecated term_chars and automatic removal of CR + LF ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In the original PyVISA implementation, ``Instrument`` takes a ``term_chars`` argument to change at the read and write termination characters. If this argument is ``None``, ``CR + LF`` is appended to each outgoing message and not expected for incoming messages (although removed if present). In PyVISA 1.6, ``term_chars`` is replaced by ``read_termination` and ``write_termination``. In this way, you can set independently the termination for each operation. Automatic removal of ``CR + LF`` is also gone in 1.6. .. _Lantz: https://lantz.readthedocs.org/ pyvisa-1.11.3/docs/source/index.rst000066400000000000000000000051651375165327600172270ustar00rootroot00000000000000:orphan: PyVISA: Control your instruments with Python ============================================ .. image:: _static/logo-full.jpg :alt: PyVISA :class: floatingflask PyVISA is a Python package that enables you to control all kinds of measurement devices independently of the interface (e.g. GPIB, RS232, USB, Ethernet). As an example, reading self-identification from a Keithley Multimeter with GPIB number 12 is as easy as three lines of Python code:: >>> import pyvisa >>> rm = pyvisa.ResourceManager() >>> rm.list_resources() ('ASRL1::INSTR', 'ASRL2::INSTR', 'GPIB0::12::INSTR') >>> inst = rm.open_resource('GPIB0::12::INSTR') >>> print(inst.query("*IDN?")) (That's the whole program; really!) It works on Windows, Linux and Mac; with arbitrary adapters (e.g. National Instruments, Agilent, Tektronix, Stanford Research Systems). General overview ---------------- The programming of measurement instruments can be real pain. There are many different protocols, sent over many different interfaces and bus systems (e.g. GPIB, RS232, USB, Ethernet). For every programming language you want to use, you have to find libraries that support both your device and its bus system. In order to ease this unfortunate situation, the Virtual Instrument Software Architecture (VISA) specification was defined in the middle of the 90ies. VISA is a standard for configuring, programming, and troubleshooting instrumentation systems comprising GPIB, VXI, PXI, Serial, Ethernet, and/or USB interfaces. Today VISA is implemented on all significant operating systems. A couple of vendors offer VISA libraries, partly with free download. These libraries work together with arbitrary peripherical devices, although they may be limited to certain interface devices, such as the vendor's GPIB card. The VISA specification has explicit bindings to Visual Basic, C, and G (LabVIEW’s graphical language). Python can be used to call functions from a VISA shared library (`.dll`, `.so`, `.dylib`) allowing to directly leverage the standard implementations. In addition, Python can be used to directly access most bus systems used by instruments which is why one can envision to implement the VISA standard directly in Python (see the `PyVISA-Py` project for more details). PyVISA is both a Python wrapper for VISA shared libraries but can also serve as a front-end for other VISA implementation such as `PyVISA-Py`. .. toctree:: :maxdepth: 2 User guide Advanced topics FAQ API Documentation .. LocalWords: rst british reST ies vpp pyvisa docs pyvLab pyvisa-1.11.3/docs/source/introduction/000077500000000000000000000000001375165327600201005ustar00rootroot00000000000000pyvisa-1.11.3/docs/source/introduction/communication.rst000066400000000000000000000235151375165327600235050ustar00rootroot00000000000000.. _intro-communication: Communicating with your instrument ================================== .. include:: ../substitutions.sub .. note:: If you have been using PyVISA before version 1.5, you might want to read :ref:`faq-migrating`. An example ---------- Let's go *in medias res* and have a look at a simple example:: >>> import pyvisa >>> rm = pyvisa.ResourceManager() >>> rm.list_resources() ('ASRL1::INSTR', 'ASRL2::INSTR', 'GPIB0::14::INSTR') >>> my_instrument = rm.open_resource('GPIB0::14::INSTR') >>> print(my_instrument.query('*IDN?')) This example already shows the two main design goals of PyVISA: preferring simplicity over generality, and doing it the object-oriented way. After importing ``pyvisa``, we create a ``ResourceManager`` object. If called without arguments, PyVISA will prefer the default backend (IVI) which tries to find the VISA shared library for you. If it fails it will fall back to pyvisa-py if installed. You can check what backend is used and the location of the shared library used, if relevant, simply by: >>> print(rm) .. note:: In some cases, PyVISA is not able to find the library for you resulting in an ``OSError``. To fix it, find the library path yourself and pass it to the ResourceManager constructor. You can also specify it in a configuration file as discussed in :ref:`intro-configuring`. Once that you have a ``ResourceManager``, you can list the available resources using the ``list_resources`` method. The output is a tuple listing the :ref:`intro-resource-names`. You can use a dedicated regular expression syntax to filter the instruments discovered by this method. The syntax is described in details in |list_resources|. The default value is '?*::INSTR' which means that by default only instrument whose resource name ends with '::INSTR' are listed (in particular USB RAW resources and TCPIP SOCKET resources are not listed). In this case, there is a GPIB instrument with instrument number 14, so you ask the ``ResourceManager`` to open "'GPIB0::14::INSTR'" and assign the returned object to the *my_instrument*. Notice ``open_resource`` has given you an instance of ``GPIBInstrument`` class (a subclass of the more generic ``Resource``). >>> print(my_instrument) There many ``Resource`` subclasses representing the different types of resources, but you do not have to worry as the ``ResourceManager`` will provide you with the appropriate class. You can check the methods and attributes of each class in the :ref:`api_resources` Then, you query the device with the following message: ``'\*IDN?'``. Which is the standard GPIB message for "what are you?" or -- in some cases -- "what's on your display at the moment?". ``query`` is a short form for a ``write`` operation to send a message, followed by a ``read``. So:: >>> my_instrument.query("*IDN?") is the same as:: >>> my_instrument.write('*IDN?') >>> print(my_instrument.read()) .. note:: You can access all the opened resources by calling ``rm.list_opened_resources()``. This will return a list of ``Resource``, however note that this list is not dynamically updated. Getting the instrument configuration right ------------------------------------------ For most instruments, you actually need to properly configure the instrument so that it understands the message sent by the computer (in particular how to identifies the end of the commands) and so that computer knows when the instrument is done talking. If you don't you are likely to see a |VisaIOError| reporting a timeout. For message based instruments (which covers most of the use cases), this usually consists in properly setting the |read_termination| and |write_termination| attribute of the resource. Resources have more attributes described in :ref:`intro-resources`, but for now we will focus on those two. The first place to look for the values you should set for your instrument is the manual. The information you are looking is usually located close to the beginning of the IO operation section of the manual. If you cannot find the value, you can try to iterate through a couple of standard values but this is not recommended approach. Once you have that information you can try to configure your instrument and start communicating as follows:: >>> my_instrument.read_termination = '\n' >>> my_instrument.write_termination = '\n' >>> my_instrument.query('*IDN?') Here we use `'\n'` known as 'line feed'. This is a common value, another one is `'\r'` i.e. 'carriage return', and in some cases the null byte '\0' is used. In an ideal world, this will work and you will be able to get an answer from your instrument. If it does not, it means the settings are likely wrong (the documentation does not always shine by its clarity). In the following we will discuss common debugging tricks, if nothing works feel free to post on the PyVISA `issue tracker`_. If you do be sure to describe in detail your setup and what you already attempted. .. _`issue tracker`: https://github.com/pyvisa/pyvisa/issues .. note:: The particular case of reading back large chunk of data either in ASCII or binary format is not discussed below but in :ref:`intro-rvalues`. Making sure the instrument understand the command ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ When using query, we are testing both writing to and reading from the instrument. The first thing to do is to try to identify if the issue occurs during the write or the read operation. If your instrument has a front panel, you can check for errors (some instrument will display a transient message right after the read). If an error occurs, it may mean your command string contains a mistake or the instrument is using a different set of command (some instrument supports both a legacy set of commands and SCPI commands). If you see no error it means that either the instrument did not detect the end of your message or you just cannot read it. The next step is to determine in what situation we are. To do so, you can look for a command that would produce a visible/measurable change on the instrument and send it. In the absence of errors, if the expected change did not occur it means the instrument did not understand that the command was complete. This points out to an issue with the |write_termination|. At this stage, you can go back to the manual (some instruments allow to switch between the recognized values), or try standards values (such as `'\n'`, `'\r'`, combination of those two, `'\0'`). Assuming you were able to confirm that the instrument understood the command you sent, it means the reading part is the issue, which is easier to troubleshoot. You can try different standard values for the |read_termination|, but if nothing works you can use the |read_bytes| method. This method will read at most the number of bytes specified. So you can try reading one byte at a time till you encounter a time out. When that happens most likely the last character you read is the termination character. Here is a quick example: .. code:: python my_instrument.write('*IDN?') while True: print(my_instrument.read_bytes(1)) If |read_bytes| times out on the first read, it actually means that the instrument did not answer. If the instrument is old it may be because your are too fast for it, so you can try waiting a bit before reading (using `time.sleep` from Python standard library). Otherwise, you either use a command that does not cause any answer or actually your write does not work (go back up a couple of paragraph). .. note:: Some instruments may be slow in answering and may require you to either increase the timeout or specify a delay between the write and read operation. This can be done globally using |query_delay| or passing ``delay=0.1`` for example to wait 100 ms after writing before reading. .. note:: When transferring large amount of data the total transfer time may exceed the timeout value in which case increasing the timeout value should fix the issue. .. note:: It is possible to disable the use of teh termination character to detect the end of an input message by setting |read_termination| to ``""``. Care has to be taken for the case of serial instrument for which the method used to determine the end of input is controlled by the |end_input| attribute and is set by default to use the termination character. To fully disable the use of the termination character its value should be changed. The above focused on using only PyVISA, if you are running Windows, or MacOS you are likely to have access to third party tools that can help. Some tips to use them are given in the next section. .. note:: Some instruments do not react well to a communication error, and you may have to restart it to get it to work again. Using third-party softwares ^^^^^^^^^^^^^^^^^^^^^^^^^^^ The implementation of VISA from National Instruments and Keysight both come with tools (NIMax, Keysight Connection Expert) that can be used to figure out what is wrong with your communication setup. In both cases, you can open an interactive communication session to your instrument and tune the settings using a GUI (which can make things easier). The basic procedure is the one described above, if you can make it work in one of those tools you should be able, in most cases, to get it to work in PyVISA. However if it does not work using those tools, it won't work in PyVISA. For serial instruments (true or emulated over USB), you can also try to directly communicate with it using Putty or Tera Term on Windows, CoolTerm or Terminal / screen on macOS. Hopefully those simple tips will allow you to get through. In some cases, it may not be the case and you are always welcome to ask for help (but realize that the maintainers are unlikely to have access to the instrument you are having trouble with). pyvisa-1.11.3/docs/source/introduction/configuring.rst000066400000000000000000000073251375165327600231530ustar00rootroot00000000000000.. _intro-configuring: Configuring the backend ======================= .. include:: ../substitutions.sub Currently there are two backends available: The one included in pyvisa, which uses the IVI library (include NI-VISA, Keysight VISA, R&S VISA, tekVISA etc.), and the backend provided by pyvisa-py, which is a pure python implementation of the VISA library. If no backend is specified, pyvisa uses the IVI backend if any IVI library has been installed (see next section for details). Failing that, it uses the pyvisa-py backend. You can also select a desired backend by passing a parameter to the ResourceManager, shown here for pyvisa-py: >>> visa.ResourceManager('@py') Alternatively it can also be selected by setting the environment variable PYVISA_LIBRARY. It takes the same values as the ResourceManager constructor. Configuring the IVI backend --------------------------- .. note:: The IVI backend requires that you install first the IVI-VISA library. For example you can use NI-VISA or any other library in your opinion. about NI-VISA get info here: (:ref:`faq-getting-nivisa`) In most cases PyVISA will be able to find the location of the shared visa library. If this does not work or you want to use another one, you need to provide the library path to the |ResourceManager| constructor:: >>> rm = ResourceManager('Path to library') You can make this library the default for all PyVISA applications by using a configuration file called :file:`.pyvisarc` (mind the leading dot) in your `home directory`_. ========================== ================================================== Operating System Location ========================== ================================================== Windows NT :file:`\\WINNT\\Profiles\\` -------------------------- -------------------------------------------------- Windows 2000, XP and 2003 :file:`\\Documents and Settings\\` -------------------------- -------------------------------------------------- Windows Vista, 7 or 8 :file:`\\Users\\` -------------------------- -------------------------------------------------- Mac OS X :file:`/Users/` -------------------------- -------------------------------------------------- Linux :file:`/home/` (depends on the distro) ========================== ================================================== For example in Windows XP, place it in your user folder "Documents and Settings" folder, e.g. :file:`C:\\Documents and Settings\\smith\\.pyvisarc` if "smith" is the name of your login account. This file has the format of an INI file. For example, if the library is at :file:`/usr/lib/libvisa.so.7`, the file :file:`.pyvisarc` must contain the following:: [Paths] VISA library: /usr/lib/libvisa.so.7 Please note that `[Paths]` is treated case-sensitively. To specify extra .dll search paths on Windows, use a `.pyvisarc` file like the following:: [Paths] dll_extra_paths: C:\Program Files\Keysight\IO Libraries Suite\bin;C:\Program Files (x86)\Keysight\IO Libraries Suite\bin You can define a site-wide configuration file at :file:`/usr/share/pyvisa/.pyvisarc` (It may also be :file:`/usr/local/...` depending on the location of your Python). Under Windows, this file is usually placed at :file:`c:\\Python37\\share\\pyvisa\\.pyvisarc`. If you encounter any problem, take a look at the :ref:`faq`. There you will find the solutions to common problem as well as useful debugging techniques. If everything fails, feel free to open an issue in our `issue tracker`_ .. _`home directory`: http://en.wikipedia.org/wiki/Home_directory .. _`issue tracker`: https://github.com/pyvisa/pyvisa/issues pyvisa-1.11.3/docs/source/introduction/event_handling.rst000066400000000000000000000137421375165327600236260ustar00rootroot00000000000000.. _intro-event_handling: Event handling ============== .. include:: ../substitutions.sub VISA supports generating events on the instrument side usually when a register change and handling then on the controller using two different mechanisms: - storing the events in a queue - calling a dedicated handler function registered for that purpose when the event occurs PyVISA supports using both mechanism and tries to provide a convenient interface to both. Below we give a couple of example of how to use each mechanism (using a fictional instrument). Waiting on events using a queue ------------------------------- First let's have a look at how to wait for an event to occur which will be stored in a queue. .. code-block:: python from pyvisa import ResourceManager, constants rm = ResourceManager with rm.open_resource("TCPIP::192.168.0.2::INSTR") as instr: # Type of event we want to be notified about event_type = constants.EventType.service_request # Mechanism by which we want to be notified event_mech = constants.EventMechanism.queue instr.enable_event(event_type, event_mech) # Instrument specific code to enable service request # (for example on operation complete OPC) instr.write("*SRE 1") instr.write("INIT") # Wait for the event to occur response = instr.wait_on_event(event_type, 1000) assert response.event.event_type == event_type assert response.timed_out = False instr.disable_event(event_type, event_mech) Let's examine the code. First, to avoid repeating ourselves, we store the type of event we want to be notified about and the mechanism we want to use to be notified. And we enable event notifications. .. code:: python # Type of event we want to be notified about event_type = constants.EventType.service_request # Mechanism by which we want to be notified event_mech = constants.EventMechanism.queue instr.enable_event(event_type, event_mech) Next we need to setup our instrument to generate the kind of event at the right time and start the operation that will lead to the event. For the sake of that example we are going to consider a Service Request event. Usually service request can be enabled for a range of register state, the details depending on the instrument. One useful case is to generate a service request when an operation is complete which is we are pretending to do here. Finally we wait for the event to occur and we specify a timeout of 1000ms to avoid waiting for ever. Once we received the event we disable event handling. Registering handlers for event ------------------------------ Rather than waiting for an event, it can sometimes be convenient to take immediate action when an event occurs, in which having the VISA library call directly a function can be useful. Let see how. .. note:: One can enable event handling using both mechanisms (constants.EventMechanism.all) .. code-block:: python from time import sleep from pyvisa import ResourceManager, constants rm = ResourceManager def handle_event(resource, event, user_handle): resource.called = True print(f"Handled event {event.event_type} on {resource}") with rm.open_resource("TCPIP::192.168.0.2::INSTR") as instr: instr.called = False # Type of event we want to be notified about event_type = constants.EventType.service_request # Mechanism by which we want to be notified event_mech = constants.EventMechanism.queue wrapped = instr.wrap_handler(handle_event) user_handle = instr.install_handler(event_type, wrapped, 42) instr.enable_event(event_type, event_mech, None) # Instrument specific code to enable service request # (for example on operation complete OPC) instr.write("*SRE 1") instr.write("INIT") while not instr.called: sleep(10) instr.disable_event(event_type, event_mech) instr.uninstall_handler(event_type, wrapped, user_handle) Our handler function needs to have a specific signature to be used by VISA. The expected signature is (session, event_type, event_context, user_handle). This signature is not exactly convenient since it forces us to deal with a number of low-level details such session (ID of a resource in VISA) and event_context that serves the same purpose for events. One way to get a nicer interface is to wrap the handler using the |wrap_handler| method of the |Resource| object. The wrapped function is expected to have the following signature: (resource, event, user_handle) which the signature of our handler: .. code:: python def handle_event(resource, event, user_handle): resource.called = True print(f"Handled event {event.event_type} on {resource}") And before installing the handler, we wrap it: .. code:: python wrapped = instr.wrap_handler(handle_event) When wrapping a handler, you need to use the resource on which it is going to be installed to wrap it. Furthermore note that in order to uninstall a handler you need to keep the wrapped version around. Next we install the handler and enable the event processing: .. code:: python user_handle = instr.install_handler(event_type, wrapped, 42) instr.enable_event(event_type, event_mech, None) When installing a handler one can optionally, specify a user handle that will be passed to the handler. This handle can be used to identify which handler is called when registering the same handler multiple times on the same resource. That value may have to be converted by the backend. As a consequence the value passed to the handler may not the same as the value registered and its value will be to the backend dependent. For this reason you need to keep the converted value returned by install handler to uninstall the handler at a later time. .. note:: In the case of ctwrapper that ships with PyVISA, the value is converted to an equivalent ctypes object (c_float for a float, c_int for an integer, etc) pyvisa-1.11.3/docs/source/introduction/example.rst000066400000000000000000000052251375165327600222710ustar00rootroot00000000000000.. _more-complex-example: A more complex example ====================== .. include:: ../substitutions.sub The following example shows how to use SCPI commands with a Keithley 2000 multimeter in order to measure 10 voltages. After having read them, the program calculates the average voltage and prints it on the screen. I'll explain the program step-by-step. First, we have to initialize the instrument:: >>> keithley = rm.open_resource("GPIB::12") >>> keithley.write("*rst; status:preset; *cls") Here, we create the instrument variable *keithley*, which is used for all further operations on the instrument. Immediately after it, we send the initialization and reset message to the instrument. The next step is to write all the measurement parameters, in particular the interval time (500ms) and the number of readings (10) to the instrument. I won't explain it in detail. Have a look at an SCPI and/or Keithley 2000 manual. .. code-block:: python >>> interval_in_ms = 500 >>> number_of_readings = 10 >>> keithley.write("status:measurement:enable 512; *sre 1") >>> keithley.write("sample:count %d" % number_of_readings) >>> keithley.write("trigger:source bus") >>> keithley.write("trigger:delay %f" % (interval_in_ms / 1000.0)) >>> keithley.write("trace:points %d" % number_of_readings) >>> keithley.write("trace:feed sense1; trace:feed:control next") Okay, now the instrument is prepared to do the measurement. The next three lines make the instrument waiting for a trigger pulse, trigger it, and wait until it sends a "service request":: >>> keithley.write("initiate") >>> keithley.assert_trigger() >>> keithley.wait_for_srq() With sending the service request, the instrument tells us that the measurement has been finished and that the results are ready for transmission. We could read them with `keithley.query("trace:data?")` however, then we'd get: .. code-block:: none -000.0004E+0,-000.0005E+0,-000.0004E+0,-000.0007E+0, -000.0000E+0,-000.0007E+0,-000.0008E+0,-000.0004E+0, -000.0002E+0,-000.0005E+0 which we would have to convert to a Python list of numbers. Fortunately, the |query_ascii_values| method does this work for us:: >>> voltages = keithley.query_ascii_values("trace:data?") >>> print("Average voltage: ", sum(voltages) / len(voltages)) Finally, we should reset the instrument's data buffer and SRQ status register, so that it's ready for a new run. Again, this is explained in detail in the instrument's manual:: >>> keithley.query("status:measurement?") >>> keithley.write("trace:clear; trace:feed:control next") That's it. 18 lines of lucid code. (Well, SCPI is awkward, but that's another story.) pyvisa-1.11.3/docs/source/introduction/getting.rst000066400000000000000000000056731375165327600223060ustar00rootroot00000000000000.. _intro-getting: Installation ============ .. include:: ../substitutions.sub PyVISA is a frontend to the VISA library. It runs on Python 3.6+. You can install it using pip_:: $ pip install -U pyvisa Backend ------- In order for PyVISA to work, you need to have a suitable backend. PyVISA includes a backend that wraps the `National Instruments's VISA`_ library. However, you need to download and install the library yourself (See :ref:`faq-getting-nivisa`). There are multiple VISA implementations from different vendors. PyVISA is tested against `National Instruments's VISA`_ and `Keysight IO Library Suite`_ which can both be downloaded for free (you do not need a development environment only the driver library). .. warning:: PyVISA works with 32- and 64- bit Python and can deal with 32- and 64-bit VISA libraries without any extra configuration. What PyVISA cannot do is open a 32-bit VISA library while running in 64-bit Python (or the other way around). **You need to make sure that the Python and VISA library have the same bitness** Alternatively, you can install `PyVISA-Py`_ which is a pure Python implementation of the VISA standard. You can install it using pip_:: $ pip install -U pyvisa-py .. note:: At the moment, `PyVISA-Py` implements only a limited subset of the VISA standard and does not support all protocols on all bus systems. Please refer to its documentation for more details. Testing your installation ------------------------- That's all! You can check that PyVISA is correctly installed by starting up python, and creating a ResourceManager: >>> import pyvisa >>> rm = pyvisa.ResourceManager() >>> print(rm.list_resources()) If you encounter any problem, take a look at the :ref:`faq-faq`. There you will find the solutions to common problem as well as useful debugging techniques. If everything fails, feel free to open an issue in our `issue tracker`_ Using the development version ----------------------------- You can install the latest development version (at your own risk) directly form GitHub_:: $ pip install -U git+https://github.com/pyvisa/pyvisa.git .. note:: If you have an old system installation of Python and you don't want to mess with it, you can try `Anaconda`_. It is a free Python distribution by Continuum Analytics that includes many scientific packages. .. _easy_install: http://pypi.python.org/pypi/setuptools .. _Python: http://www.python.org/ .. _pip: http://www.pip-installer.org/ .. _`Anaconda`: https://www.anaconda.com/distribution/ .. _PyPI: https://pypi.python.org/pypi/PyVISA .. _GitHub: https://github.com/pyvisa/pyvisa .. _`National Instruments's VISA`: https://www.ni.com/en-us/support/downloads/drivers/download.ni-visa.html .. _`Keysight IO Library SUite`: https://www.keysight.com/en/pd-1985909/io-libraries-suite/ .. _`issue tracker`: https://github.com/pyvisa/pyvisa/issues .. _`PyVISA-Py`: http://pyvisa-py.readthedocs.io/en/latest/ pyvisa-1.11.3/docs/source/introduction/index.rst000066400000000000000000000006641375165327600217470ustar00rootroot00000000000000.. _intro: User guide ========== This section of the documentation will focus on getting you started with PyVISA. The following sections will cover how to install and configure the library, how to communicate with your instrument and how to debug standard communications issues. .. toctree:: :maxdepth: 2 getting configuring communication example rvalues event_handling resources shell names pyvisa-1.11.3/docs/source/introduction/names.rst000066400000000000000000000212641375165327600217420ustar00rootroot00000000000000 .. _intro-resource-names: VISA resource names =================== .. include:: ../substitutions.sub If you use the method |open_resource|, you must tell this function the *VISA resource name* of the instrument you want to connect to. Generally, it starts with the bus type, followed by a double colon ``"::"``, followed by the number within the bus. For example, .. code-block:: none GPIB::10 denotes the GPIB instrument with the number 10. If you have two GPIB boards and the instrument is connected to board number 1, you must write .. code-block:: none GPIB1::10 As for the bus, things like ``"GPIB"``, ``"USB"``, ``"ASRL"`` (for serial/parallel interface) are possible. So for connecting to an instrument at COM2, the resource name is .. code-block:: none ASRL2 (Since only one instrument can be connected with one serial interface, there is no double colon parameter.) However, most VISA systems allow aliases such as ``"COM2"`` or ``"LPT1"``. You may also add your own aliases. The resource name is case-insensitive. It doesn't matter whether you say ``"ASRL2"`` or ``"asrl2"``. For further information, I have to refer you to a comprehensive VISA description like ``_. VISA Resource Syntax and Examples --------------------------------- (This is adapted from the VISA manual) The following table shows the grammar for the address string. Optional string segments are shown in square brackets ([ ]). ================= ======================================================================================== Interface Syntax ================= ======================================================================================== ENET-Serial INSTR ASRL[0]::host address::serial port::INSTR ----------------- ---------------------------------------------------------------------------------------- GPIB INSTR GPIB[board]::primary address[::secondary address][::INSTR] GPIB INTFC GPIB[board]::INTFC ----------------- ---------------------------------------------------------------------------------------- PXI BACKPLANE PXI[interface]::chassis number::BACKPLANE PXI INSTR PXI[bus]::device[::function][::INSTR] PXI INSTR PXI[interface]::bus-device[.function][::INSTR] PXI INSTR PXI[interface]::CHASSISchassis number::SLOTslot number[::FUNCfunction][::INSTR] PXI MEMACC PXI[interface]::MEMACC ----------------- ---------------------------------------------------------------------------------------- Remote NI-VISA visa://host address[:server port]/remote resource ----------------- ---------------------------------------------------------------------------------------- Serial INSTR ASRLboard[::INSTR] ----------------- ---------------------------------------------------------------------------------------- TCPIP INSTR TCPIP[board]::host address[::LAN device name][::INSTR] TCPIP SOCKET TCPIP[board]::host address::port::SOCKET ----------------- ---------------------------------------------------------------------------------------- USB INSTR USB[board]::manufacturer ID::model code::serial number[::USB interface number][::INSTR] USB RAW USB[board]::manufacturer ID::model code::serial number[::USB interface number]::RAW ----------------- ---------------------------------------------------------------------------------------- VXI BACKPLANE VXI[board][::VXI logical address]::BACKPLANE VXI INSTR VXI[board]::VXI logical address[::INSTR] VXI MEMACC VXI[board]::MEMACC VXI SERVANT VXI[board]::SERVANT ================= ======================================================================================== Use the GPIB keyword to establish communication with GPIB resources. Use the VXI keyword for VXI resources via embedded, MXIbus, or 1394 controllers. Use the ASRL keyword to establish communication with an asynchronous serial (such as RS-232 or RS-485) device. Use the PXI keyword for PXI and PCI resources. Use the TCPIP keyword for Ethernet communication. The following table shows the default value for optional string segments. ======================== ================================== Optional String Segments Default Value ======================== ================================== board 0 GPIB secondary address none LAN device name inst0 PXI bus 0 PXI function 0 USB interface number lowest numbered relevant interface ======================== ================================== The following table shows examples of address strings: ================================ ============================================= Address String Description ================================ ============================================= ASRL::1.2.3.4::2::INSTR A serial device attached to port 2 of the ENET Serial controller at address 1.2.3.4. -------------------------------- --------------------------------------------- ASRL1::INSTR A serial device attached to interface ASRL1. -------------------------------- --------------------------------------------- GPIB::1::0::INSTR A GPIB device at primary address 1 and secondary address 0 in GPIB interface 0. -------------------------------- --------------------------------------------- GPIB2::INTFC Interface or raw board resource for GPIB interface 2. -------------------------------- --------------------------------------------- PXI::15::INSTR PXI device number 15 on bus 0 with implied function 0. -------------------------------- --------------------------------------------- PXI::2::BACKPLANE Backplane resource for chassis 2 on the default PXI system, which is interface 0. -------------------------------- --------------------------------------------- PXI::CHASSIS1::SLOT3 PXI device in slot number 3 of the PXI chassis configured as chassis 1. -------------------------------- --------------------------------------------- PXI0::2-12.1::INSTR PXI bus number 2, device 12 with function 1. -------------------------------- --------------------------------------------- PXI0::MEMACC PXI MEMACC session. -------------------------------- --------------------------------------------- TCPIP::dev.company.com::INSTR A TCP/IP device using VXI-11 or LXI located at the specified address. This uses the default LAN Device Name of inst0. -------------------------------- --------------------------------------------- TCPIP0::1.2.3.4::999::SOCKET Raw TCP/IP access to port 999 at the specified IP address. -------------------------------- --------------------------------------------- USB::0x1234::125::A22-5::INSTR A USB Test & Measurement class device with manufacturer ID 0x1234, model code 125, and serial number A22-5. This uses the device's first available USBTMC interface. This is usually number 0. -------------------------------- --------------------------------------------- USB::0x5678::0x33::SN999::1::RAW A raw USB nonclass device with manufacturer ID 0x5678, model code 0x33, and serial number SN999. This uses the device's interface number 1. -------------------------------- --------------------------------------------- visa://hostname/ASRL1::INSTR The resource ASRL1::INSTR on the specified remote system. -------------------------------- --------------------------------------------- VXI::1::BACKPLANE Mainframe resource for chassis 1 on the default VXI system, which is interface 0. -------------------------------- --------------------------------------------- VXI::MEMACC Board-level register access to the VXI interface. -------------------------------- --------------------------------------------- VXI0::1::INSTR A VXI device at logical address 1 in VXI interface VXI0. -------------------------------- --------------------------------------------- VXI0::SERVANT Servant/device-side resource for VXI interface 0. ================================ ============================================= pyvisa-1.11.3/docs/source/introduction/resources.rst000066400000000000000000000162141375165327600226500ustar00rootroot00000000000000.. _intro-resources: Resources ========= .. include:: ../substitutions.sub A resource represents an instrument, e.g. a measurement device. There are multiple classes derived from resources representing the different available types of resources (eg. GPIB, Serial). Each contains the particular set of attributes an methods that are available by the underlying device. You do not create this objects directly but they are returned by the |open_resource| method of a |ResourceManager|. In general terms, there are two main groups derived from |Resource|, |MessageBasedResource| and |RegisterBasedResource|. .. note:: The resource Python class to use is selected automatically from the resource name. However, you can force a Resource Python class: >>> from pyvisa.resources import MessageBasedResource >>> inst = rm.open('ASRL1::INSTR', resource_pyclass=MessageBasedResource) The following sections explore the most common attributes of ``Resource`` and ``MessageBased`` (Serial, GPIB, etc) which are the ones you will encounter more often. For more information, refer to the :ref:`api`. Attributes of Resource ---------------------- session ~~~~~~~ Each communication channel to an instrument has a session handle which is unique. You can get this value:: >>> my_device.session 10442240 If the resource is closed, an exception will be raised: >>> inst.close() >>> inst.session Traceback (most recent call last): ... pyvisa.errors.InvalidSession: Invalid session handle. The resource might be closed. timeout ~~~~~~~ Very most VISA I/O operations may be performed with a timeout. If a timeout is set, every operation that takes longer than the timeout is aborted and an exception is raised. Timeouts are given per instrument in **milliseconds**. For all PyVISA objects, a timeout is set with .. code-block:: python my_device.timeout = 25000 Here, ``my_device`` may be a device, an interface or whatever, and its timeout is set to 25 seconds. To set an **infinite** timeout, set it to ``None`` or ``float('+inf')`` or: .. code-block:: python del my_device.timeout To set it to **immediate**, set it to `0` or a negative value. (Actually, any value smaller than 1 is considered immediate) Now every operation of the resource takes as long as it takes, even indefinitely if necessary. Attributes of MessageBase resources ----------------------------------- .. _sec:chunk-length: Chunk length ~~~~~~~~~~~~ If you read data from a device, you must store it somewhere. Unfortunately, PyVISA must make space for the data *before* it starts reading, which means that it must know how much data the device will send. However, it doesn't know a priori. Therefore, PyVISA reads from the device in *chunks*. Each chunk is 20 kilobytes long by default. If there's still data to be read, PyVISA repeats the procedure and eventually concatenates the results and returns it to you. Those 20 kilobytes are large enough so that mostly one read cycle is sufficient. The whole thing happens automatically, as you can see. Normally you needn't worry about it. However, some devices don't like to send data in chunks. So if you have trouble with a certain device and expect data lengths larger than the default chunk length, you should increase its value by saying e.g. :: my_instrument.chunk_size = 102400 This example sets it to 100 kilobytes. .. _sec:termchars: Termination characters ~~~~~~~~~~~~~~~~~~~~~~ Somehow the computer must detect when the device is finished with sending a message. It does so by using different methods, depending on the bus system. In most cases you don't need to worry about termination characters because the defaults are very good. However, if you have trouble, you may influence termination characters with PyVISA. Termination characters may be one character or a sequence of characters. Whenever this character or sequence occurs in the input stream, the read operation is terminated and the read message is given to the calling application. The next read operation continues with the input stream immediately after the last termination sequence. In PyVISA, the termination characters are stripped off the message before it is given to you. You may set termination characters for each instrument, e.g. .. code-block:: python my_instrument.read_termination = '\r' ('\r' is carriage return, usually appearing in the manuals as CR) Alternatively you can give it when creating your instrument object:: my_instrument = rm.open_resource("GPIB::10", read_termination='\r') The default value depends on the bus system. Generally, the sequence is empty, in particular for GPIB. For RS232 it's ``\r``. You can specify the character to add to each outgoing message using the ``write_termination`` attribute. .. note:: Under the hood PyVISA manipulates several VISA attributes in a coherent manner. You can also access those directly if you need to see the :ref:visa-attr section below. `query_delay` and `send_end` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. index:: single: query_delay single: send_end There are two further options related to message termination, namely ``send_end`` and ``query_delay``. ``send_end`` is a boolean. If it's ``True`` (the default), the EOI line is asserted after each write operation, signalling the end of the operation. EOI is GPIB-specific but similar action is taken for other interfaces. The argument ``query_delay`` is the time in seconds to wait after each write operation when performing a query. So you could write:: my_instrument = rm.open_resource("GPIB::10", send_end=False, delay=1.2) .. index:: single: EOI line This will set the delay to 1.2 seconds, and the EOI line is omitted. By the way, omitting EOI is *not* recommended, so if you omit it nevertheless, you should know what you're doing. .. _visa-attr: VISA attributes --------------- In addition to the above mentioned attributes, you can access most of the VISA attributes as defined in the visa standard on your resources through properties. Those properties will take for you of converting Python values to values VISA values and hence simplify their manipulations. Some of those attributes also have lighter aliases that makes them easier to access as illustrated below: .. code:: python from pyvisa import constants, ResourceManager rm = ResourceManager() instr = rm.open_resource('TCPIP0::1.2.3.4::56789::SOCKET') instr.io_protocol = constants.VI_PROT_4882_STRS # is equivalent to instr.VI_ATTR_IO_PROT = constants.VI_PROT_4882_STRS .. note:: To know the full list of attribute available on a resource you can inspect |visa_attributes_classes| or if you are using ``pyvisa-shell`` simply use the ``attr`` command. You can also manipulate the VISA attributes using |get_visa_attribute| and |set_visa_attribute|. However you will have use the proper values (as defined in :mod:`pyvisa.constants`) both to access the attribute and to specify the value. .. code:: python from pyvisa import constants, ResourceManager rm = ResourceManager() instr = rm.open_resource('TCPIP0::1.2.3.4::56789::SOCKET') instr.set_visa_attribute(constants.VI_ATTR_SUPPRESS_END_EN, constants.VI_TRUE) pyvisa-1.11.3/docs/source/introduction/rvalues.rst000066400000000000000000000174061375165327600223230ustar00rootroot00000000000000.. _intro-rvalues: Reading and Writing values ========================== .. include:: ../substitutions.sub Some instruments allow to transfer to and from the computer larger datasets with a single query. A typical example is an oscilloscope, which you can query for the whole voltage trace. Or an arbitrary wave generator to which you have to transfer the function you want to generate. Basically, data like this can be transferred in two ways: in ASCII form (slow, but human readable) and binary (fast, but more difficult to debug). PyVISA Message Based Resources have different methods for this called |read_ascii_values|, |query_ascii_values| and |read_binary_values|, |query_binary_values|. Reading ASCII values -------------------- If your oscilloscope (open in the variable ``inst``) has been configured to transfer data in **ASCII** when the ``CURV?`` command is issued, you can just query the values like this:: >>> values = inst.query_ascii_values('CURV?') ``values`` will be ``list`` containing the values from the device. In many cases you do not want a ``list`` but rather a different container type such as a ``numpy.array``. You can of course cast the data afterwards like this:: >>> values = np.array(inst.query_ascii_values('CURV?')) but sometimes it is much more efficient to avoid the intermediate list, and in this case you can just specify the container type in the query:: >>> values = inst.query_ascii_values('CURV?', container=numpy.array) In ``container``, you can have any callable/type that takes an iterable. .. note:: When using numpy.array or numpy.ndarray, PyVISA will use numpy routines to optimize the conversion by avoiding the use of an intermediate representation. Some devices transfer data in ASCII but not as decimal numbers but rather hex or oct. Or you might want to receive an array of strings. In that case you can specify a ``converter``. For example, if you expect to receive integers as hex: >>> values = inst.query_ascii_values('CURV?', converter='x') ``converter`` can be one of the Python :ref:`string formatting codes `. But you can also specify a callable that takes a single argument if needed. The default converter is ``'f'``. Finally, some devices might return the values separated in an uncommon way. For example if the returned values are separated by a ``'$'`` you can do the following call: >>> values = inst.query_ascii_values('CURV?', separator='$') You can provide a function to takes a string and returns an iterable. Default value for the separator is ``','`` (comma) .. _sec:reading-binary-data: Reading binary values --------------------- If your oscilloscope (open in the variable ``inst``) has been configured to transfer data in **BINARY** when the ``CURV?`` command is issued, you need to know which type datatype (e.g. uint8, int8, single, double, etc) is being used. PyVISA use the same naming convention as the :ref:`struct module `. You also need to know the *endianness*. PyVISA assumes little-endian as default. If you have doubles `d` in big endian the call will be:: >>> values = inst.query_binary_values('CURV?', datatype='d', is_big_endian=True) You can also specify the output container type, just as it was shown before. By default, PyVISA will assume that the data block is formatted according to the IEEE convention. If your instrument uses HP data block you can pass ``header_fmt='hp'`` to ``read_binary_values``. If your instrument does not use any header for the data simply ``header_fmt='empty'``. By default PyVISA assumes, that the instrument will add the termination character at the end of the data block and actually makes sure it reads it to avoid issues. This behavior fits well a number of devices. However some devices omit the termination character, in which cases the operation will timeout. In this situation, first makes sure you can actually read from the instrument by reading the answer using the ``read_raw`` function (you may need to call it multiple time), and check that the advertized length of the block match what you get from your instrument (plus the header). If it is so, then you can safely pass ``expect_termination=False``, and PyVISA will not look for a termination character at the end of the message. If you can read without any problem from your instrument, but cannot retrieve the full message when using this method (VI_ERROR_CONN_LOST, VI_ERROR_INV_SETUP, or Python simply crashes), try passing different values for ``chunk_size``(the default is 20*1024). The underlying mechanism for this issue is not clear but changing ``chunk_size`` has been used to work around it. Note that using larger chunk sizes for large transfer may result in a speed up of the transfer. In some cases, the instrument may use a protocol that does not indicate how many bytes will be transferred. The Keithley 2000 for example always return the full buffer whose size is reported by the 'trace:points?' command. Since a binary block may contain the termination character, PyVISA need to know how many bytes to expect. For those case, you can pass the expected number of points using the ``data_points`` keyword argument. The number of bytes will be inferred from the datatype of the block. Finally if you are reading a file for example and simply want to extract a bytes object, you can use the ``"s"`` datatype and pass ``bytes`` as container. Writing ASCII values -------------------- To upload a function shape to arbitrary wave generator, the command might be ``WLISt:WAVeform:DATA ,`` where ```` tells the device under which name to store the data. >>> values = list(range(100)) >>> inst.write_ascii_values('WLISt:WAVeform:DATA somename,', values) Again, you can specify the converter code. >>> inst.write_ascii_values('WLISt:WAVeform:DATA somename,', values, converter='x') ``converter`` can be one of the Python :ref:`string formatting codes `. But you can also specify a callable that takes a single argument if needed. The default converter is ``'f'``. The separator can also be specified just like in ``query_ascii_values``. >>> inst.write_ascii_values('WLISt:WAVeform:DATA somename,', values, converter='x', separator='$') You can provide a function to takes a iterable and returns an string. Default value for the separator is ``','`` (comma) Writing binary values --------------------- To upload a function shape to arbitrary wave generator, the command might be ``WLISt:WAVeform:DATA ,`` where ```` tells the device under which name to store the data. >>> values = list(range(100)) >>> inst.write_binary_values('WLISt:WAVeform:DATA somename,', values) Again you can specify the ``datatype`` and ``endianness``. >>> inst.write_binary_values('WLISt:WAVeform:DATA somename,', values, datatype='d', is_big_endian=False) If your data are already in a ``bytes`` object you can use the ``"s"`` format. When things are not what they should be --------------------------------------- PyVISA provides an easy way to transfer data from and to the device. The methods described above work fine for 99% of the cases but there is always a particular device that do not follow any of the standard protocols and is so different that cannot be adapted with the arguments provided above. In those cases, you need to get the data:: >>> inst.write('CURV?') >>> data = inst.read_raw() and then you need to implement the logic to parse it. Alternatively if the `read_raw` call fails you can try to read just a few bytes using:: >>> inst.write('CURV?') >>> data = inst.read_bytes(1) If this call fails it may mean that your instrument did not answer, either because it needs more time or because your first instruction was not understood. pyvisa-1.11.3/docs/source/introduction/shell.rst000066400000000000000000000224471375165327600217520ustar00rootroot00000000000000.. _intro-shell: PyVISA Shell ============ .. include:: ../substitutions.sub The shell, moved into PyVISA from the Lantz_ Project is a text based user interface to interact with instruments. You can invoke it from the command-line:: pyvisa-shell that will show something the following prompt:: Welcome to the VISA shell. Type help or ? to list commands. (visa) At any time, you can type ``?`` or ``help`` to get a list of valid commands:: (visa) help Documented commands (type help ): ======================================== EOF attr close exit help list open query read timeout write (visa) help list List all connected resources. Tab completion is also supported. The most basic task is listing all connected devices:: (visa) list ( 0) ASRL1::INSTR ( 1) ASRL2::INSTR ( 2) USB0::0x1AB1::0x0588::DS1K00005888::INSTR Each device/port is assigned a number that you can use for subsequent commands. Let's open comport 1:: (visa) open 0 ASRL1::INSTR has been opened. You can talk to the device using "write", "read" or "query. The default end of message is added to each message (open) query *IDN? Some Instrument, Some Company. You can print timeout that is set for query/read operation:: (open) timeout Timeout: 2000ms Then also to change the timeout for example to 1500ms (1.5 sec):: (open) timeout 1500 Done We can also get a list of all visa attributes:: (open) attr +-----------------------------+------------+----------------------------+-------------------------------------+ | VISA name | Constant | Python name | val | +-----------------------------+------------+----------------------------+-------------------------------------+ | VI_ATTR_ASRL_ALLOW_TRANSMIT | 1073676734 | allow_transmit | 1 | | VI_ATTR_ASRL_AVAIL_NUM | 1073676460 | bytes_in_buffer | 0 | | VI_ATTR_ASRL_BAUD | 1073676321 | baud_rate | 9600 | | VI_ATTR_ASRL_BREAK_LEN | 1073676733 | break_length | 250 | | VI_ATTR_ASRL_BREAK_STATE | 1073676732 | break_state | 0 | | VI_ATTR_ASRL_CONNECTED | 1073676731 | | VI_ERROR_NSUP_ATTR | | VI_ATTR_ASRL_CTS_STATE | 1073676462 | | 0 | | VI_ATTR_ASRL_DATA_BITS | 1073676322 | data_bits | 8 | | VI_ATTR_ASRL_DCD_STATE | 1073676463 | | 0 | | VI_ATTR_ASRL_DISCARD_NULL | 1073676464 | discard_null | 0 | | VI_ATTR_ASRL_DSR_STATE | 1073676465 | | 0 | | VI_ATTR_ASRL_DTR_STATE | 1073676466 | | 1 | | VI_ATTR_ASRL_END_IN | 1073676467 | end_input | 2 | | VI_ATTR_ASRL_END_OUT | 1073676468 | | 0 | | VI_ATTR_ASRL_FLOW_CNTRL | 1073676325 | | 0 | | VI_ATTR_ASRL_PARITY | 1073676323 | parity | 0 | | VI_ATTR_ASRL_REPLACE_CHAR | 1073676478 | replace_char | 0 | | VI_ATTR_ASRL_RI_STATE | 1073676479 | | 0 | | VI_ATTR_ASRL_RTS_STATE | 1073676480 | | 1 | | VI_ATTR_ASRL_STOP_BITS | 1073676324 | stop_bits | 10 | | VI_ATTR_ASRL_WIRE_MODE | 1073676735 | | 128 | | VI_ATTR_ASRL_XOFF_CHAR | 1073676482 | xoff_char | 19 | | VI_ATTR_ASRL_XON_CHAR | 1073676481 | xon_char | 17 | | VI_ATTR_DMA_ALLOW_EN | 1073676318 | allow_dma | 0 | | VI_ATTR_FILE_APPEND_EN | 1073676690 | | 0 | | VI_ATTR_INTF_INST_NAME | 3221160169 | | ASRL1 (/dev/cu.Bluetooth-PDA-Sync) | | VI_ATTR_INTF_NUM | 1073676662 | interface_number | 1 | | VI_ATTR_INTF_TYPE | 1073676657 | | 4 | | VI_ATTR_IO_PROT | 1073676316 | io_protocol | 1 | | VI_ATTR_MAX_QUEUE_LENGTH | 1073676293 | | 50 | | VI_ATTR_RD_BUF_OPER_MODE | 1073676330 | | 3 | | VI_ATTR_RD_BUF_SIZE | 1073676331 | | 4096 | | VI_ATTR_RM_SESSION | 1073676484 | | 3160976 | | VI_ATTR_RSRC_CLASS | 3221159937 | resource_class | INSTR | | VI_ATTR_RSRC_IMPL_VERSION | 1073676291 | implementation_version | 5243392 | | VI_ATTR_RSRC_LOCK_STATE | 1073676292 | lock_state | 0 | | VI_ATTR_RSRC_MANF_ID | 1073676661 | | 4086 | | VI_ATTR_RSRC_MANF_NAME | 3221160308 | resource_manufacturer_name | National Instruments | | VI_ATTR_RSRC_NAME | 3221159938 | resource_name | ASRL1::INSTR | | VI_ATTR_RSRC_SPEC_VERSION | 1073676656 | spec_version | 5243136 | | VI_ATTR_SEND_END_EN | 1073676310 | send_end | 1 | | VI_ATTR_SUPPRESS_END_EN | 1073676342 | | 0 | | VI_ATTR_TERMCHAR | 1073676312 | | 10 | | VI_ATTR_TERMCHAR_EN | 1073676344 | | 0 | | VI_ATTR_TMO_VALUE | 1073676314 | | 2000 | | VI_ATTR_TRIG_ID | 1073676663 | | -1 | | VI_ATTR_WR_BUF_OPER_MODE | 1073676333 | | 2 | | VI_ATTR_WR_BUF_SIZE | 1073676334 | | 4096 | +-----------------------------+------------+----------------------------+-------------------------------------+ To simplify the handling of VI_ATTR_TERMCHAR and VI_ATTR_TERMCHAR_EN, the command 'termchar' can be used. If only one character provided, it sets both read and write termination character to the same character. If two characters are provided, it sets read and write termination characters independently. To setup termchar to '\r' (CR or ascii code 10):: (open) termchar CR Done To read what termchar is defined:: (open) termchar Termchar read: CR write: CR To setup read termchar to '\n' and write termchar to '\r\n\':: (open) termchar LF CRLF Done Supported termchar values are: CR ('\r'), LF ('\n'), CRLF ('\r\n') , NUL ('\0'), None. None is used to disable termchar. Finally, you can close the device:: (open) close PyVisa Shell Backends --------------------- Based on available backend (see bellow for ``info`` command), it is possible to switch shell to use non-default backend via ``-b BACKEND`` or ``--backend BACKEND``. You can invoke:: pyvisa-shell -b sim to use python-sim as backend instead of ni backend. This can be used for example for testing of python-sim configuration. You can invoke:: pyvisa-shell -b py uses python-py as backend instead of ivi backend, for situation when ivi not installed. PyVisa Info ----------- You can invoke it from the command-line:: pyvisa-info that will print information to diagnose PyVISA, info about Machine, Python, backends, etc :: Machine Details: Platform ID: Windows Processor: Intel64 Family 6 ... PyVISA Version: ... Backends: ni: Version: 1.8 (bundled with PyVISA) ... py: Version: 0.2 ... sim: Version: 0.3 Spec version: 1.1 Summary ------- Cool, right? It will be great to have a GUI similar to NI-MAX, but we leave that to be developed outside PyVISA. Want to help? Let us know! .. _`Lantz`: https://lantz.readthedocs.org pyvisa-1.11.3/docs/source/substitutions.sub000066400000000000000000000044141375165327600210340ustar00rootroot00000000000000.. This file holds some common substitutions (mainly for referencing code). To use it add the directive include:: substitutions.rst at the beginning of the file. .. ============================================================================ .. PyVISA substitutions .. ============================================================================ .. |VisaLibraryBase| replace:: :class:`~pyvisa.highlevel.VisaLibraryBase` .. |ResourceManager| replace:: :class:`~pyvisa.highlevel.ResourceManager` .. |open_resource| replace:: :meth:`~pyvisa.highlevel.ResourceManager.open_resource` .. |list_resources| replace:: :py:meth:`~pyvisa.highlevel.ResourceManager.list_resources` .. |visalib| replace:: :attr:`~pyvisa.highlevel.ResourceManager.visalib` .. |Event| replace:: :class:`~pyvisa.events.Event` .. |Resource| replace:: :class:`~pyvisa.resources.Resource` .. |MessageBasedResource| replace:: :class:`~pyvisa.resources.MessageBasedResource` .. |query_delay| replace:: :attr:`~pyvisa.resources.MessageBasedResource.query_delay` .. |read_bytes| replace:: :meth:`~pyvisa.resources.MessageBasedResource.read_bytes` .. |read_ascii_values| replace:: :meth:`~pyvisa.resources.MessageBasedResource.read_ascii_values` .. |read_binary_values| replace:: :meth:`~pyvisa.resources.MessageBasedResource.read_binary_values` .. |query_ascii_values| replace:: :meth:`~pyvisa.resources.MessageBasedResource.query_ascii_values` .. |query_binary_values| replace:: :meth:`~pyvisa.resources.MessageBasedResource.query_binary_values` .. |read_termination| replace:: :attr:`~pyvisa.resources.MessageBasedResource.read_termination` .. |write_termination| replace:: :attr:`~pyvisa.resources.MessageBasedResource.write_termination` .. |visa_attributes_classes| replace:: :attr:`~pyvisa.resources.Resource.visa_attributes_classes` .. |get_visa_attribute| replace:: :attr:`~pyvisa.resources.Resource.get_visa_attribute` .. |set_visa_attribute| replace:: :attr:`~pyvisa.resources.Resource.set_visa_attribute` .. |wrap_handler| replace:: :attr:`~pyvisa.resources.Resource.wrap_handler` .. |end_input| replace:: :attr:`~pyvisa.resources.serial.SerialInstrument.end_input` .. |RegisterBasedResource| replace:: :class:`~pyvisa.resources.RegisterBasedResource` .. |VisaIOError| replace:: :exc:`~pyvisa.errors.VisaIOError` pyvisa-1.11.3/examples/000077500000000000000000000000001375165327600147455ustar00rootroot00000000000000pyvisa-1.11.3/examples/itc4.py000066400000000000000000000034301375165327600161620ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # # itc4.py - PyVISA test code for Oxfort ITC4 temperature controller # # Copyright © 2005, 2006, 2007, 2008 # Torsten Bronger , # Gregor Thalhammer . # # This file is part of PyVISA. # # PyVISA is free software; you can redistribute it and/or modify it under # the terms of the MIT licence: # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # from __future__ import division, unicode_literals, print_function, absolute_import import visa def test_itc4(): print("Test start") itc4 = visa.Instrument("COM2", term_chars=b"\r", timeout=5) itc4.write(b"V") print(itc4.read()) print("Test end") pyvisa-1.11.3/examples/keithley2000.py000066400000000000000000000042531375165327600174430ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # # keithley2000.py - PyVISA test code for Keithley 2000 multimeter # # Copyright © 2005, 2006, 2007, 2008 # Torsten Bronger , # Gregor Thalhammer . # # This file is part of PyVISA. # # PyVISA is free software; you can redistribute it and/or modify it under # the terms of the MIT licence: # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # from __future__ import division, unicode_literals, print_function, absolute_import import visa def test_keithley2000(monkeypatch): monkeypatch.setattr(visa.GpibInstrument, "interface_type", VI_INTF_GPIB) monkeypatch.setattr(visa.GpibInstrument, "stb", 0x40) print("Test start") keithley = visa.GpibInstrument(12) milliseconds = 500 number_of_values = 10 keithley.write( ("F0B2M2G0T2Q%dI%dX" % (milliseconds, number_of_values)).encode("ascii") ) keithley.trigger() keithley.wait_for_srq() voltages = keithley.read_floats() if voltages: print("Average: ", sum(voltages) / len(voltages)) print("Test end") pyvisa-1.11.3/pyproject.toml000066400000000000000000000002241375165327600160410ustar00rootroot00000000000000[build-system] requires = ["setuptools>=42", "wheel", "setuptools_scm[toml]>=3.4.3"] build-backend = "setuptools.build_meta" [tool.setuptools_scm] pyvisa-1.11.3/pyvisa/000077500000000000000000000000001375165327600144425ustar00rootroot00000000000000pyvisa-1.11.3/pyvisa/__init__.py000066400000000000000000000033631375165327600165600ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Python wrapper of IVI Virtual Instruments Software Architecture library (VISA). This file is part of PyVISA. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ import logging import sys if sys.version_info >= (3, 8): from importlib.metadata import version, PackageNotFoundError else: from importlib_metadata import version, PackageNotFoundError # type: ignore # Defined here since it is imported in other pyvisa modules logger = logging.getLogger("pyvisa") logger.addHandler(logging.NullHandler()) from .errors import ( Error, InvalidBinaryFormat, InvalidSession, LibraryError, OSNotSupported, UnknownHandler, VisaIOError, VisaIOWarning, VisaTypeError, ) from .highlevel import ResourceManager from .resources import Resource # noqa : F401 This is needed to register all resources. def log_to_screen(level=logging.DEBUG) -> None: log_to_stream(None, level) # sys.stderr by default def log_to_stream(stream_output, level=logging.DEBUG) -> None: logger.setLevel(level) ch = logging.StreamHandler(stream_output) ch.setLevel(level) formatter = logging.Formatter( "%(asctime)s - %(name)s - %(levelname)s - %(message)s" ) ch.setFormatter(formatter) logger.addHandler(ch) __version__ = "unknown" try: __version__ = version(__name__) except PackageNotFoundError: # package is not installed pass __all__ = [ "ResourceManager", "logger", "Error", "VisaIOError", "VisaIOWarning", "VisaTypeError", "UnknownHandler", "OSNotSupported", "InvalidBinaryFormat", "InvalidSession", "LibraryError", "log_to_screen", "log_to_stream", ] pyvisa-1.11.3/pyvisa/attributes.py000066400000000000000000002746241375165327600172210ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Descriptor to access VISA attributes. Not all descriptors are used but they provide a reference regarding the possible values for each attributes. This file is part of PyVISA. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ import enum import sys from collections import defaultdict from typing import ( TYPE_CHECKING, Any, Dict, Generic, List, Optional, Set, SupportsBytes, SupportsInt, Tuple, Type, TypeVar, Union, overload, ) from typing_extensions import ClassVar, DefaultDict from . import constants, util if TYPE_CHECKING: from .events import Event, IOCompletionEvent # noqa # pragma: no cover from .resources import Resource # noqa # pragma: no cover #: Not available value. NotAvailable = object() #: Attribute for all session types. class AllSessionTypes: # We use a class to simplify typing """Class used as a placeholder to indicate an attribute exist on all resources.""" pass #: Map resource to attribute AttributesPerResource: DefaultDict[ Union[ Tuple[constants.InterfaceType, str], Type[AllSessionTypes], constants.EventType ], Set[Type["Attribute"]], ] = defaultdict(set) #: Map id to attribute AttributesByID: Dict[int, Type["Attribute"]] = dict() # --- Descriptor classes --------------------------------------------------------------- T = TypeVar("T") class Attribute(Generic[T]): """Base class for Attributes to be used as properties.""" #: List of resource or event types with this attribute. #: each element is a tuple (constants.InterfaceType, str) resources: ClassVar[ Union[ List[Union[Tuple[constants.InterfaceType, str], constants.EventType]], Type[AllSessionTypes], ] ] = [] #: Name of the Python property to be matched to this attribute. py_name: ClassVar[str] = "To be specified" #: Name of the VISA Attribute visa_name: ClassVar[str] = "To be specified" #: Type of the VISA attribute visa_type: ClassVar[str] = "" #: Numeric constant of the VISA Attribute attribute_id: ClassVar[int] = 0 #: Default value fo the VISA Attribute default: ClassVar[Any] = "N/A" #: Access read: ClassVar[bool] = False write: ClassVar[bool] = False local: ClassVar[bool] = False __doc__: str @classmethod def __init_subclass__(cls, **kwargs): """Register the subclass with the supported resources.""" super().__init_subclass__(**kwargs) if not cls.__name__.startswith("AttrVI_"): return cls.attribute_id = getattr(constants, cls.visa_name) # Check that the docstring are populated before extending them # Cover the case of running with Python with -OO option if cls.__doc__ is not None: cls.redoc() if cls.resources is AllSessionTypes: AttributesPerResource[AllSessionTypes].add(cls) else: for res in cls.resources: AttributesPerResource[res].add(cls) AttributesByID[cls.attribute_id] = cls @classmethod def redoc(cls) -> None: """Generate a descriptive docstring.""" cls.__doc__ += "\n:VISA Attribute: %s (%s)" % (cls.visa_name, cls.attribute_id) def post_get(self, value: Any) -> T: """Override to check or modify the value returned by the VISA function. Parameters ---------- value : Any Value returned by the VISA library. Returns ------- T Equivalent python value. """ return value def pre_set(self, value: T) -> Any: """Override to check or modify the value to be passed to the VISA function. Parameters ---------- value : T Python value to be passed to VISA library. Returns ------- Any Equivalent value to pass to the VISA library. """ return value @overload def __get__(self, instance: None, owner) -> "Attribute": pass @overload # noqa: F811 def __get__(self, instance: Union["Resource", "Event"], owner) -> T: # noqa: F811 pass def __get__(self, instance, owner): # noqa: F811 """Access a VISA attribute and convert to a nice Python representation.""" if instance is None: return self if not self.read: raise AttributeError("can't read attribute") return self.post_get(instance.get_visa_attribute(self.attribute_id)) def __set__(self, instance: "Resource", value: T) -> None: """Set the attribute if writable.""" if not self.write: raise AttributeError("can't write attribute") # Here we use the bare integer value of the enumeration hence the type ignore instance.set_visa_attribute( self.attribute_id, # type: ignore self.pre_set(value), ) @classmethod def in_resource(cls, session_type: Tuple[constants.InterfaceType, str]) -> bool: """Is the attribute part of a given session type. Parameters ---------- session_type : Tuple[constants.InterfaceType, str] Type of session for which to check the presence of an attribute. Returns ------- bool Is the attribute present. """ if cls.resources is AllSessionTypes: return True return session_type in cls.resources # type: ignore class EnumAttribute(Attribute): """Class for attributes with values that map to a PyVISA Enum.""" #: Enum type with valid values. enum_type: ClassVar[Type[enum.IntEnum]] @classmethod def redoc(cls) -> None: """Add the enum member to the docstring.""" super(EnumAttribute, cls).redoc() cls.__doc__ += "\n:type: :class:%s.%s" % ( cls.enum_type.__module__, cls.enum_type.__name__, ) def post_get(self, value: Any) -> enum.IntEnum: """Convert the VISA value to the proper enum member.""" return self.enum_type(value) def pre_set(self, value: enum.IntEnum) -> Any: """Validate the value passed against the enum.""" # Python 3.8 raise if a non-Enum is used for value try: value = self.enum_type(value) except ValueError: raise ValueError( "%r is an invalid value for attribute %s, " "should be a %r" % (value, self.visa_name, self.enum_type) ) return value class IntAttribute(Attribute): """Class for attributes with integers values.""" @classmethod def redoc(cls) -> None: """Add the type of the returned value.""" super(IntAttribute, cls).redoc() cls.__doc__ += "\n:type: int" def post_get(self, value: SupportsInt) -> int: """Convert the returned value to an integer.""" return int(value) class RangeAttribute(IntAttribute): """Class for integer attributes with values within a range.""" #: Range for the value, and iterable of extra values. min_value: int max_value: int values: Optional[List[int]] = None @classmethod def redoc(cls) -> None: """Specify the range of validity for the attribute.""" super(RangeAttribute, cls).redoc() cls.__doc__ += "\n:range: %s <= value <= %s" % (cls.min_value, cls.max_value) if cls.values: cls.__doc__ += " or in %s" % cls.values def pre_set(self, value: int) -> int: """Check that the value falls in the specified range.""" if not self.min_value <= value <= self.max_value: if not self.values: raise ValueError( "%r is an invalid value for attribute %s, " "should be between %r and %r" % (value, self.visa_name, self.min_value, self.max_value) ) elif value not in self.values: raise ValueError( "%r is an invalid value for attribute %s, " "should be between %r and %r or %r" % ( value, self.visa_name, self.min_value, self.max_value, self.values, ) ) return value class ValuesAttribute(Attribute): """Class for attributes with values in a list.""" #: Valid values values: list = [] @classmethod def redoc(cls) -> None: """Add the allowed values to teh docs.""" super(ValuesAttribute, cls).redoc() cls.__doc__ += "\n:values: %s" % cls.values def pre_set(self, value: int) -> int: """Validate the value against the allowed values.""" if value not in self.values: raise ValueError( "%r is an invalid value for attribute %s, " "should be in %s" % (value, self.visa_name, self.values) ) return value class BooleanAttribute(Attribute): """Class for attributes with boolean values.""" py_type: bool @classmethod def redoc(cls) -> None: """Add the type to the docs.""" super(BooleanAttribute, cls).redoc() cls.__doc__ += "\n:type: bool" def post_get(self, value: constants.VisaBoolean) -> bool: """Convert to a Python boolean.""" return value == constants.VisaBoolean.true def pre_set(self, value: bool) -> constants.VisaBoolean: """Convert to a VISA boolean.""" return constants.VisaBoolean.true if value else constants.VisaBoolean.false class CharAttribute(Attribute): """Class for attributes with char values.""" py_type = str @classmethod def redoc(cls) -> None: """Specify the valid characters.""" super(CharAttribute, cls).redoc() cls.__doc__ += "\nASCII Character\n:type: str | bytes" def post_get(self, value: int) -> str: """Convert the integer to a character.""" return chr(value) def pre_set(self, value: Union[str, bytes]) -> int: """Convert a character to an integer.""" return ord(value) # --- Session attributes --------------------------------------------------------------- # Attributes are in the same order as in the constants.ResourceAttribute enum # VI_ATTR_RM_SESSION is not implemented as resource property, # use .resource_manager.session instead class AttrVI_ATTR_INTF_TYPE(EnumAttribute): """Interface type of the given session.""" resources = AllSessionTypes py_name = "interface_type" visa_name = "VI_ATTR_INTF_TYPE" visa_type = "ViUInt16" default = NotAvailable read, write, local = True, False, False enum_type = constants.InterfaceType class AttrVI_ATTR_INTF_NUM(RangeAttribute): """Board number for the given interface.""" resources = AllSessionTypes py_name = "interface_number" visa_name = "VI_ATTR_INTF_NUM" visa_type = "ViUInt16" default = 0 read, write, local = True, False, False min_value, max_value, values = 0x0, 0xFFFF, None class AttrVI_ATTR_INTF_INST_NAME(Attribute): """Human-readable text that describes the given interface.""" resources = AllSessionTypes py_name = "" visa_name = "VI_ATTR_INTF_INST_NAME" visa_type = "ViString" default = NotAvailable read, write, local = True, False, False class AttrVI_ATTR_RSRC_CLASS(Attribute): """Resource class as defined by the canonical resource name. Possible values are: INSTR, INTFC, SOCKET, RAW... """ resources = AllSessionTypes py_name = "resource_class" visa_name = "VI_ATTR_RSRC_CLASS" visa_type = "ViString" default = NotAvailable read, write, local = True, False, False class AttrVI_ATTR_RSRC_NAME(Attribute): """Unique identifier for a resource compliant with the address structure.""" resources = AllSessionTypes py_name = "resource_name" visa_name = "VI_ATTR_RSRC_NAME" visa_type = "ViRsrc" default = NotAvailable read, write, local = True, False, False class AttrVI_ATTR_RSRC_IMPL_VERSION(RangeAttribute): """Resource version that identifies the revisions or implementations of a resource. This attribute value is defined by the individual manufacturer and increments with each new revision. The format of the value has the upper 12 bits as the major number of the version, the next lower 12 bits as the minor number of the version, and the lowest 8 bits as the sub-minor number of the version. """ resources = AllSessionTypes py_name = "implementation_version" visa_name = "VI_ATTR_RSRC_IMPL_VERSION" visa_type = "ViVersion" default = NotAvailable read, write, local = True, False, True min_value, max_value, values = 0, 4294967295, None class AttrVI_ATTR_RSRC_LOCK_STATE(EnumAttribute): """Current locking state of the resource. The resource can be unlocked, locked with an exclusive lock, or locked with a shared lock. """ resources = AllSessionTypes py_name = "lock_state" visa_name = "VI_ATTR_RSRC_LOCK_STATE" visa_type = "ViAccessMode" default = constants.AccessModes.no_lock read, write, local = True, False, False enum_type = constants.AccessModes class AttrVI_ATTR_RSRC_SPEC_VERSION(RangeAttribute): """Version of the VISA specification to which the implementation is compliant. The format of the value has the upper 12 bits as the major number of the version, the next lower 12 bits as the minor number of the version, and the lowest 8 bits as the sub-minor number of the version. The current VISA specification defines the value to be 00300000h. """ resources = AllSessionTypes py_name = "spec_version" visa_name = "VI_ATTR_RSRC_SPEC_VERSION" visa_type = "ViVersion" default = 0x00300000 read, write, local = True, False, True min_value, max_value, values = 0, 4294967295, None class AttrVI_ATTR_RSRC_MANF_NAME(Attribute): """Manufacturer name of the vendor that implemented the VISA library. This attribute is not related to the device manufacturer attributes. Note The value of this attribute is for display purposes only and not for programmatic decisions, as the value can differ between VISA implementations and/or revisions. """ resources = AllSessionTypes py_name = "resource_manufacturer_name" visa_name = "VI_ATTR_RSRC_MANF_NAME" visa_type = "ViString" default = NotAvailable read, write, local = True, False, False class AttrVI_ATTR_RSRC_MANF_ID(RangeAttribute): """VXI manufacturer ID of the vendor that implemented the VISA library. This attribute is not related to the device manufacturer attributes. """ resources = AllSessionTypes py_name = "" visa_name = "VI_ATTR_RSRC_MANF_ID" visa_type = "ViUInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 0, 0x3FFF, None class AttrVI_ATTR_TMO_VALUE(RangeAttribute): """Timeout in milliseconds for all resource I/O operations. This value is used when accessing the device associated with the given session. Special values: - **immediate** (``VI_TMO_IMMEDIATE``): 0 (for convenience, any value smaller than 1 is considered as 0) - **infinite** (``VI_TMO_INFINITE``): ``float('+inf')`` (for convenience, None is considered as ``float('+inf')``) To set an **infinite** timeout, you can also use: >>> del instrument.timeout A timeout value of VI_TMO_IMMEDIATE means that operations should never wait for the device to respond. A timeout value of VI_TMO_INFINITE disables the timeout mechanism. """ resources = AllSessionTypes py_name = "timeout" visa_name = "VI_ATTR_TMO_VALUE" visa_type = "ViUInt32" default = 2000 read, write, local = True, True, True min_value, max_value, values = 0, 0xFFFFFFFF, None def pre_set(self, value: Optional[Union[int, float]]) -> int: """Convert the timeout to an integer recognized by the VISA library.""" timeout = util.cleanup_timeout(value) return timeout def post_get(self, value: int) -> Union[int, float]: # type: ignore """Convert VI_TMO_INFINTE into float("+inf").""" if value == constants.VI_TMO_INFINITE: return float("+inf") return value def __delete__(self, instance: "Resource") -> None: """Set an infinite timeout upon deletion.""" instance.set_visa_attribute( constants.ResourceAttribute.timeout_value, constants.VI_TMO_INFINITE ) class AttrVI_ATTR_MAX_QUEUE_LENGTH(RangeAttribute): """Maximum number of events that can be queued at any time on the given session. Events that occur after the queue has become full will be discarded. """ resources = AllSessionTypes py_name = "" visa_name = "VI_ATTR_MAX_QUEUE_LENGTH" visa_type = "ViUInt32" default = 50 read, write, local = True, True, True min_value, max_value, values = 0x1, 0xFFFFFFFF, None class AttrVI_ATTR_USER_DATA(RangeAttribute): """Maximum number of events that can be queued at any time on the given session. Events that occur after the queue has become full will be discarded. """ resources = AllSessionTypes py_name = "" visa_name = "VI_ATTR_USER_DATA" visa_type = "ViUInt64" if constants.is_64bits else "ViUInt32" default = 0 read, write, local = True, True, True min_value, max_value, values = ( 0x0, 0xFFFFFFFFFFFFFFFF if constants.is_64bits else 0xFFFFFFFF, None, ) class AttrVI_ATTR_TRIG_ID(EnumAttribute): """Identifier for the current triggering mechanism.""" resources = [ (constants.InterfaceType.gpib, "INSTR"), (constants.InterfaceType.gpib, "INTFC"), (constants.InterfaceType.pxi, "INSTR"), (constants.InterfaceType.pxi, "BACKPLANE"), (constants.InterfaceType.asrl, "INSTR"), (constants.InterfaceType.tcpip, "INSTR"), (constants.InterfaceType.vxi, "BACKPLANE"), (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "SERVANT"), ] py_name = "" visa_name = "VI_ATTR_TRIG_ID" visa_type = "ViInt16" default = constants.VI_TRIG_SW read, write, local = True, True, True enum_type = constants.TriggerID class AttrVI_ATTR_SEND_END_EN(BooleanAttribute): """Should END be asserted during the transfer of the last byte of the buffer.""" # TODO find out if USB RAW should be listed resources = [ (constants.InterfaceType.asrl, "INSTR"), (constants.InterfaceType.gpib, "INSTR"), (constants.InterfaceType.gpib, "INTFC"), (constants.InterfaceType.tcpip, "INSTR"), (constants.InterfaceType.tcpip, "SOCKET"), (constants.InterfaceType.usb, "INSTR"), (constants.InterfaceType.usb, "RAW"), (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "SERVANT"), ] py_name = "send_end" visa_name = "VI_ATTR_SEND_END_EN" visa_type = "ViBoolean" default = True read, write, local = True, True, True class AttrVI_ATTR_SUPPRESS_END_EN(BooleanAttribute): """Whether to suppress the END indicator termination. Only relevant in viRead and related operations. """ resources = [ (constants.InterfaceType.asrl, "INSTR"), (constants.InterfaceType.gpib, "INSTR"), (constants.InterfaceType.tcpip, "INSTR"), (constants.InterfaceType.tcpip, "SOCKET"), (constants.InterfaceType.usb, "INSTR"), (constants.InterfaceType.usb, "RAW"), (constants.InterfaceType.vxi, "INSTR"), ] py_name = "" visa_name = "VI_ATTR_SUPPRESS_END_EN" visa_type = "ViBoolean" default = False read, write, local = True, True, True class AttrVI_ATTR_TERMCHAR_EN(BooleanAttribute): """Should the read operation terminate when a termination character is received. This attribute is ignored if VI_ATTR_ASRL_END_IN is set to VI_ASRL_END_TERMCHAR. This attribute is valid for both raw I/O (viRead) and formatted I/O (viScanf). For message based resource this automatically handled by the `read_termination` property. """ resources = [ (constants.InterfaceType.gpib, "INSTR"), (constants.InterfaceType.gpib, "INTFC"), (constants.InterfaceType.asrl, "INSTR"), (constants.InterfaceType.tcpip, "INSTR"), (constants.InterfaceType.tcpip, "SOCKET"), (constants.InterfaceType.usb, "INSTR"), (constants.InterfaceType.usb, "RAW"), (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "SERVANT"), ] py_name = "" visa_name = "VI_ATTR_TERMCHAR_EN" visa_type = "ViBoolean" default = False read, write, local = True, True, True class AttrVI_ATTR_TERMCHAR(CharAttribute): """VI_ATTR_TERMCHAR is the termination character. When the termination character is read and VI_ATTR_TERMCHAR_EN is enabled during a read operation, the read operation terminates. For message based resource this automatically handled by the `read_termination` property. """ resources = [ (constants.InterfaceType.gpib, "INSTR"), (constants.InterfaceType.gpib, "INTFC"), (constants.InterfaceType.asrl, "INSTR"), (constants.InterfaceType.tcpip, "INSTR"), (constants.InterfaceType.tcpip, "SOCKET"), (constants.InterfaceType.usb, "INSTR"), (constants.InterfaceType.usb, "RAW"), (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "SERVANT"), ] py_name = "" visa_name = "VI_ATTR_TERMCHAR" visa_type = "ViUInt8" default = 0x0A # (linefeed) read, write, local = True, True, True class AttrVI_ATTR_IO_PROT(EnumAttribute): """IO protocol to use. In VXI, you can choose normal word serial or fast data channel (FDC). In GPIB, you can choose normal or high-speed (HS-488) transfers. In serial, TCPIP, or USB RAW, you can choose normal transfers or 488.2-defined strings. In USB INSTR, you can choose normal or vendor-specific transfers. """ # Crossing IVI and NI this is correct resources = [ (constants.InterfaceType.gpib, "INTFC"), (constants.InterfaceType.gpib, "INSTR"), (constants.InterfaceType.asrl, "INSTR"), (constants.InterfaceType.tcpip, "INSTR"), (constants.InterfaceType.tcpip, "SOCKET"), (constants.InterfaceType.usb, "INSTR"), (constants.InterfaceType.usb, "RAW"), (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "SERVANT"), ] py_name = "io_protocol" visa_name = "VI_ATTR_IO_PROT" visa_type = "ViUInt16" default = constants.IOProtocol.normal read, write, local = True, True, True enum_type = constants.IOProtocol class AttrVI_ATTR_FILE_APPEND_EN(BooleanAttribute): """Should viReadToFile() overwrite (truncate) or append when opening a file.""" resources = [ (constants.InterfaceType.gpib, "INSTR"), (constants.InterfaceType.gpib, "INTFC"), (constants.InterfaceType.asrl, "INSTR"), (constants.InterfaceType.tcpip, "INSTR"), (constants.InterfaceType.tcpip, "SOCKET"), (constants.InterfaceType.usb, "INSTR"), (constants.InterfaceType.usb, "RAW"), (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "SERVANT"), ] py_name = "" visa_name = "VI_ATTR_FILE_APPEND_EN" visa_type = "ViBoolean" default = False read, write, local = True, True, True class AttrVI_ATTR_RD_BUF_OPER_MODE(RangeAttribute): """Operational mode of the formatted I/O read buffer. When the operational mode is set to VI_FLUSH_DISABLE (default), the buffer is flushed only on explicit calls to viFlush(). If the operational mode is set to VI_FLUSH_ON_ACCESS, the read buffer is flushed every time a viScanf() (or related) operation completes. """ resources = [ (constants.InterfaceType.gpib, "INSTR"), (constants.InterfaceType.gpib, "INTFC"), (constants.InterfaceType.asrl, "INSTR"), (constants.InterfaceType.tcpip, "INSTR"), (constants.InterfaceType.tcpip, "SOCKET"), (constants.InterfaceType.usb, "INSTR"), (constants.InterfaceType.usb, "RAW"), (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "SERVANT"), ] py_name = "" visa_name = "VI_ATTR_RD_BUF_OPER_MODE" visa_type = "ViUInt16" default = constants.VI_FLUSH_DISABLE read, write, local = True, True, True min_value, max_value, values = 0, 65535, None class AttrVI_ATTR_RD_BUF_SIZE(RangeAttribute): """Current size of the formatted I/O input buffer for this session. The user can modify this value by calling viSetBuf(). """ resources = [ (constants.InterfaceType.gpib, "INSTR"), (constants.InterfaceType.gpib, "INTFC"), (constants.InterfaceType.asrl, "INSTR"), (constants.InterfaceType.tcpip, "INSTR"), (constants.InterfaceType.tcpip, "SOCKET"), (constants.InterfaceType.usb, "INSTR"), (constants.InterfaceType.usb, "RAW"), (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "SERVANT"), ] py_name = "" visa_name = "VI_ATTR_RD_BUF_SIZE" visa_type = "ViUInt32" default = NotAvailable read, write, local = True, False, True min_value, max_value, values = 0, 4294967295, None class AttrVI_ATTR_WR_BUF_OPER_MODE(RangeAttribute): """Operational mode of the formatted I/O write buffer. When the operational mode is set to VI_FLUSH_WHEN_FULL (default), the buffer is flushed when an END indicator is written to the buffer, or when the buffer fills up. If the operational mode is set to VI_FLUSH_ON_ACCESS, the write buffer is flushed under the same conditions, and also every time a viPrintf() (or related) operation completes. """ resources = [ (constants.InterfaceType.gpib, "INSTR"), (constants.InterfaceType.gpib, "INTFC"), (constants.InterfaceType.asrl, "INSTR"), (constants.InterfaceType.tcpip, "INSTR"), (constants.InterfaceType.tcpip, "SOCKET"), (constants.InterfaceType.usb, "INSTR"), (constants.InterfaceType.usb, "RAW"), (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "SERVANT"), ] py_name = "" visa_name = "VI_ATTR_WR_BUF_OPER_MODE" visa_type = "ViUInt16" default = constants.VI_FLUSH_WHEN_FULL read, write, local = True, True, True min_value, max_value, values = 0, 65535, None class AttrVI_ATTR_WR_BUF_SIZE(RangeAttribute): """Current size of the formatted I/O output buffer for this session. The user can modify this value by calling viSetBuf(). """ resources = [ (constants.InterfaceType.gpib, "INSTR"), (constants.InterfaceType.gpib, "INTFC"), (constants.InterfaceType.asrl, "INSTR"), (constants.InterfaceType.tcpip, "INSTR"), (constants.InterfaceType.tcpip, "SOCKET"), (constants.InterfaceType.usb, "INSTR"), (constants.InterfaceType.usb, "RAW"), (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "SERVANT"), ] py_name = "" visa_name = "VI_ATTR_WR_BUF_SIZE" visa_type = "ViUInt32" default = NotAvailable read, write, local = True, False, True min_value, max_value, values = 0, 4294967295, None class AttrVI_ATTR_DMA_ALLOW_EN(BooleanAttribute): """Should I/O accesses use DMA (True) or Programmed I/O (False). In some implementations, this attribute may have global effects even though it is documented to be a local attribute. Since this affects performance and not functionality, that behavior is acceptable. """ # TODO find a reliable source to check if USB RAW should be listed resources = [ (constants.InterfaceType.gpib, "INSTR"), (constants.InterfaceType.gpib, "INTFC"), (constants.InterfaceType.pxi, "INSTR"), (constants.InterfaceType.asrl, "INSTR"), (constants.InterfaceType.tcpip, "INSTR"), (constants.InterfaceType.tcpip, "SOCKET"), (constants.InterfaceType.usb, "INSTR"), (constants.InterfaceType.usb, "RAW"), (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "MEMACC"), (constants.InterfaceType.vxi, "SERVANT"), ] py_name = "allow_dma" visa_name = "VI_ATTR_DMA_ALLOW_EN" visa_type = "ViBoolean" default = NotAvailable read, write, local = True, True, True class AttrVI_ATTR_TCPIP_ADDR(Attribute): """TCPIP address of the device to which the session is connected. This string is formatted in dot notation. """ resources = [ (constants.InterfaceType.tcpip, "INSTR"), (constants.InterfaceType.tcpip, "SOCKET"), ] py_name = "" visa_name = "VI_ATTR_TCPIP_ADDR" visa_type = "ViString" default = NotAvailable read, write, local = True, False, False class AttrVI_ATTR_TCPIP_HOSTNAME(Attribute): """Host name of the device. If no host name is available, this attribute returns an empty string. """ resources = [ (constants.InterfaceType.tcpip, "INSTR"), (constants.InterfaceType.tcpip, "SOCKET"), ] py_name = "" visa_name = "VI_ATTR_TCPIP_HOSTNAME" visa_type = "ViString" default = NotAvailable read, write, local = True, False, False class AttrVI_ATTR_TCPIP_PORT(RangeAttribute): """Port number for a given TCPIP address. For a TCPIP SOCKET Resource, this is a required part of the address string. """ resources = [(constants.InterfaceType.tcpip, "SOCKET")] py_name = "" visa_name = "VI_ATTR_TCPIP_PORT" visa_type = "ViUInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 0, 0xFFFF, None class AttrVI_ATTR_TCPIP_DEVICE_NAME(Attribute): """LAN device name used by the VXI-11 or LXI protocol during connection.""" resources = [(constants.InterfaceType.tcpip, "INSTR")] py_name = "" visa_name = "VI_ATTR_TCPIP_DEVICE_NAME" visa_type = "ViString" default = NotAvailable read, write, local = True, False, False class AttrVI_ATTR_TCPIP_NODELAY(BooleanAttribute): """The Nagle algorithm is disabled when this attribute is enabled (and vice versa). The Nagle algorithm improves network performance by buffering "send" data until a full-size packet can be sent. This attribute is enabled by default in VISA to verify that synchronous writes get flushed immediately. """ resources = [(constants.InterfaceType.tcpip, "SOCKET")] py_name = "" visa_name = "VI_ATTR_TCPIP_NODELAY" visa_type = "ViBoolean" default = True read, write, local = True, True, True class AttrVI_ATTR_TCPIP_KEEPALIVE(BooleanAttribute): """Requests that a TCP/IP provider enable the use of keep-alive packets. After the system detects that a connection was dropped, VISA returns a lost connection error code on subsequent I/O calls on the session. The time required for the system to detect that the connection was dropped is dependent on the system and is not settable. """ resources = [(constants.InterfaceType.tcpip, "SOCKET")] py_name = "" visa_name = "VI_ATTR_TCPIP_KEEPALIVE" visa_type = "ViBoolean" default = False read, write, local = True, True, True class AttrVI_ATTR_TCPIP_IS_HISLIP(BooleanAttribute): """Does this resource use the HiSLIP protocol.""" resources = [(constants.InterfaceType.tcpip, "INSTR")] py_name = "" visa_name = "VI_ATTR_TCPIP_IS_HISLIP" visa_type = "ViBoolean" default = NotAvailable read, write, local = True, False, False class AttrVI_ATTR_TCPIP_HISLIP_VERSION(RangeAttribute): """HiSLIP protocol version used for a particular HiSLIP connetion. Currently, HiSLIP version 1.0 would return a ViVersion value of 0x00100000. """ resources = [(constants.InterfaceType.tcpip, "INSTR")] py_name = "" visa_name = "VI_ATTR_TCPIP_HISLIP_VERSION" visa_type = "ViVersion" default = NotAvailable read, write, local = True, False, True min_value, max_value, values = 0, 0xFFFFFFFF, None class AttrVI_ATTR_TCPIP_HISLIP_OVERLAP_EN(BooleanAttribute): """Enables HiSLIP ‘Overlap’ mode. The value defaults to the mode suggested by the instrument on HiSLIP connection. If disabled, the connection uses ‘Synchronous’ mode to detect and recover from interrupted errors. If enabled, the connection uses ‘Overlapped’ mode to allow overlapped responses. If changed, VISA will do a Device Clear operation to change the mode. """ resources = [(constants.InterfaceType.tcpip, "INSTR")] py_name = "" visa_name = "VI_ATTR_TCPIP_HISLIP_OVERLAP_EN" visa_type = "ViBoolean" default = NotAvailable read, write, local = True, True, True class AttrVI_ATTR_TCPIP_HISLIP_MAX_MESSAGE_KB(RangeAttribute): """Maximum HiSLIP message size in kilobytes VISA will accept from a HiSLIP system. Defaults to 1024 (a 1 MB maximum message size). """ resources = [(constants.InterfaceType.tcpip, "INSTR")] py_name = "" visa_name = "VI_ATTR_TCPIP_HISLIP_MAX_MESSAGE_KB" visa_type = "ViUint32" default = 1024 read, write, local = True, True, True min_value, max_value, values = 0, 0xFFFFFFFF, None class AttrVI_ATTR_GPIB_PRIMARY_ADDR(RangeAttribute): """Primary address of the GPIB device used by the given session. For the GPIB INTFC Resource, this attribute is Read-Write. """ resources = [ (constants.InterfaceType.gpib, "INSTR"), (constants.InterfaceType.gpib, "INTFC"), ] py_name = "primary_address" visa_name = "VI_ATTR_GPIB_PRIMARY_ADDR" visa_type = "ViUInt16" default = NotAvailable read, write, local = True, True, False min_value, max_value, values = 0, 30, None class AttrVI_ATTR_GPIB_SECONDARY_ADDR(RangeAttribute): """Secondary address of the GPIB device used by the given session. For the GPIB INTFC Resource, this attribute is Read-Write. """ resources = [ (constants.InterfaceType.gpib, "INSTR"), (constants.InterfaceType.gpib, "INTFC"), ] py_name = "secondary_address" visa_name = "VI_ATTR_GPIB_SECONDARY_ADDR" visa_type = "ViUInt16" default = NotAvailable read, write, local = True, True, False min_value, max_value, values = 0, 30, [constants.VI_NO_SEC_ADDR] class AttrVI_ATTR_GPIB_SYS_CNTRL_STATE(BooleanAttribute): """Is the specified GPIB interface currently the system controller. In some implementations, this attribute may be modified only through a configuration utility. On these systems this attribute is read-only (RO). """ resources = [(constants.InterfaceType.gpib, "INTFC")] py_name = "is_system_controller" visa_name = "VI_ATTR_GPIB_SYS_CNTRL_STATE" visa_type = "ViBoolean" default = NotAvailable read, write, local = True, True, False class AttrVI_ATTR_GPIB_CIC_STATE(BooleanAttribute): """Is the specified GPIB interface currently CIC (Controller In Charge).""" resources = [(constants.InterfaceType.gpib, "INTFC")] py_name = "is_controller_in_charge" visa_name = "VI_ATTR_GPIB_CIC_STATE" visa_type = "ViBoolean" default = NotAvailable read, write, local = True, False, False class AttrVI_ATTR_GPIB_REN_STATE(EnumAttribute): """Current state of the GPIB REN (Remote ENable) interface line.""" resources = [ (constants.InterfaceType.gpib, "INSTR"), (constants.InterfaceType.gpib, "INTFC"), ] py_name = "remote_enabled" visa_name = "VI_ATTR_GPIB_REN_STATE" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False enum_type = constants.LineState class AttrVI_ATTR_GPIB_ATN_STATE(EnumAttribute): """Current state of the GPIB ATN (ATtentioN) interface line.""" resources = [(constants.InterfaceType.gpib, "INTFC")] py_name = "atn_state" visa_name = "VI_ATTR_GPIB_ATN_STATE" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False enum_type = constants.LineState class AttrVI_ATTR_GPIB_NDAC_STATE(EnumAttribute): """Current state of the GPIB NDAC (Not Data ACcepted) interface line.""" resources = [(constants.InterfaceType.gpib, "INTFC")] py_name = "ndac_state" visa_name = "VI_ATTR_GPIB_NDAC_STATE" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False enum_type = constants.LineState class AttrVI_ATTR_GPIB_SRQ_STATE(EnumAttribute): """Current state of the GPIB SRQ (Service ReQuest) interface line.""" resources = [(constants.InterfaceType.gpib, "INTFC")] py_name = "" visa_name = "VI_ATTR_GPIB_SRQ_STATE" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False enum_type = constants.LineState class AttrVI_ATTR_GPIB_ADDR_STATE(EnumAttribute): """Current state of the GPIB interface. The interface can be addressed to talk or listen, or not addressed. """ resources = [(constants.InterfaceType.gpib, "INTFC")] py_name = "address_state" visa_name = "VI_ATTR_GPIB_ADDR_STATE" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False enum_type = constants.AddressState class AttrVI_ATTR_GPIB_UNADDR_EN(BooleanAttribute): """Whether to unaddress the device (UNT and UNL) after each read/write operation.""" resources = [(constants.InterfaceType.gpib, "INSTR")] py_name = "enable_unaddressing" visa_name = "VI_ATTR_GPIB_UNADDR_EN" visa_type = "ViBoolean" default = False read, write, local = True, True, True class AttrVI_ATTR_GPIB_READDR_EN(BooleanAttribute): """Whether to use repeat addressing before each read/write operation.""" resources = [(constants.InterfaceType.gpib, "INSTR")] py_name = "enable_repeat_addressing" visa_name = "VI_ATTR_GPIB_READDR_EN" visa_type = "ViBoolean" default = True read, write, local = True, True, True class AttrVI_ATTR_GPIB_HS488_CBL_LEN(RangeAttribute): """Total number of meters of GPIB cable used in the specified GPIB interface.""" resources = [(constants.InterfaceType.gpib, "INTFC")] py_name = "" visa_name = "VI_ATTR_GPIB_HS488_CBL_LEN" visa_type = "ViInt16" default = NotAvailable read, write, local = True, True, False min_value, max_value, values = ( 1, 15, [constants.VI_GPIB_HS488_DISABLED, constants.VI_GPIB_HS488_NIMPL], ) class AttrVI_ATTR_ASRL_AVAIL_NUM(RangeAttribute): """Number of bytes available in the low- level I/O receive buffer.""" resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "bytes_in_buffer" visa_name = "VI_ATTR_ASRL_AVAIL_NUM" visa_type = "ViUInt32" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 0, 0xFFFFFFFF, None class AttrVI_ATTR_ASRL_BAUD(RangeAttribute): """Baud rate of the interface. It is represented as an unsigned 32-bit integer so that any baud rate can be used, but it usually requires a commonly used rate such as 300, 1200, 2400, or 9600 baud. """ resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "baud_rate" visa_name = "VI_ATTR_ASRL_BAUD" visa_type = "ViUInt32" default = 9600 read, write, local = True, True, False min_value, max_value, values = 0, 0xFFFFFFFF, None class AttrVI_ATTR_ASRL_DATA_BITS(RangeAttribute): """Number of data bits contained in each frame (from 5 to 8). The data bits for each frame are located in the low-order bits of every byte stored in memory. """ resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "data_bits" visa_name = "VI_ATTR_ASRL_DATA_BITS" visa_type = "ViUInt16" default = 8 read, write, local = True, True, False min_value, max_value, values = 5, 8, None class AttrVI_ATTR_ASRL_PARITY(EnumAttribute): """Parity used with every frame transmitted and received.""" resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "parity" visa_name = "VI_ATTR_ASRL_PARITY" visa_type = "ViUInt16" default = constants.Parity.none read, write, local = True, True, False enum_type = constants.Parity class AttrVI_ATTR_ASRL_STOP_BITS(EnumAttribute): """Number of stop bits used to indicate the end of a frame. The value VI_ASRL_STOP_ONE5 indicates one-and-one-half (1.5) stop bits. """ resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "stop_bits" visa_name = "VI_ATTR_ASRL_STOP_BITS" visa_type = "ViUInt16" default = constants.StopBits.one read, write, local = True, True, False enum_type = constants.StopBits class AttrVI_ATTR_ASRL_FLOW_CNTRL(EnumAttribute): """Indicate the type of flow control used by the transfer mechanism.""" resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "flow_control" visa_name = "VI_ATTR_ASRL_FLOW_CNTRL" visa_type = "ViUInt16" default = constants.VI_ASRL_FLOW_NONE read, write, local = True, True, False enum_type = constants.ControlFlow class AttrVI_ATTR_ASRL_DISCARD_NULL(BooleanAttribute): """If set to True, NUL characters are discarded. Otherwise, they are treated as normal data characters. For binary transfers, set this attribute to VI_FALSE. """ resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "discard_null" visa_name = "VI_ATTR_ASRL_DISCARD_NULL" visa_type = "ViBoolean" default = False read, write, local = True, True, False class AttrVI_ATTR_ASRL_CONNECTED(BooleanAttribute): """Whether the port is properly connected to another port or device. This attribute is valid only with serial drivers developed by National Instruments and documented to support this feature with the corresponding National Instruments hardware. """ resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "" visa_name = "VI_ATTR_ASRL_CONNECTED" visa_type = "ViBoolean" default = NotAvailable read, write, local = True, False, False class AttrVI_ATTR_ASRL_ALLOW_TRANSMIT(BooleanAttribute): """Manually control transmission. If set to False, suspend transmission as if an XOFF character has been received. If set to True, it resumes transmission as if an XON character has been received. """ resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "allow_transmit" visa_name = "VI_ATTR_ASRL_ALLOW_TRANSMIT" visa_type = "ViBoolean" default = True read, write, local = True, True, False class AttrVI_ATTR_ASRL_END_IN(EnumAttribute): """Method used to terminate read operations.""" resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "end_input" visa_name = "VI_ATTR_ASRL_END_IN" visa_type = "ViUInt16" default = constants.SerialTermination.termination_char read, write, local = True, True, True enum_type = constants.SerialTermination class AttrVI_ATTR_ASRL_END_OUT(EnumAttribute): """Method used to terminate write operations.""" resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "end_output" visa_name = "VI_ATTR_ASRL_END_OUT" visa_type = "ViUInt16" default = constants.SerialTermination.none read, write, local = True, True, True enum_type = constants.SerialTermination class AttrVI_ATTR_ASRL_BREAK_LEN(RangeAttribute): """Duration (in milliseconds) of the break signal. The break signal is asserted when VI_ATTR_ASRL_END_OUT is set to constants.SerialTermination.termination_break. If you want to control the assertion state and length of a break signal manually, use the VI_ATTR_ASRL_BREAK_STATE attribute instead. """ resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "break_length" visa_name = "VI_ATTR_ASRL_BREAK_LEN" visa_type = "ViInt16" default = 250 read, write, local = True, True, True min_value, max_value, values = -32768, 32767, None class AttrVI_ATTR_ASRL_BREAK_STATE(EnumAttribute): """Manually control the assertion state of the break signal. If set to constants.LineState.asserted, it suspends character transmission and places the transmission line in a break state until this attribute is reset to constants.LineState.unasserted. If you want VISA to send a break signal after each write operation automatically, use the VI_ATTR_ASRL_BREAK_LEN and VI_ATTR_ASRL_END_OUT attributes instead. """ resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "break_state" visa_name = "VI_ATTR_ASRL_BREAK_STATE" visa_type = "ViInt16" default = constants.LineState.unasserted read, write, local = True, True, False enum_type = constants.LineState class AttrVI_ATTR_ASRL_REPLACE_CHAR(CharAttribute): """Character to be used to replace incoming characters that arrive with errors. This refers for example to character that arrives with parity error. """ resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "replace_char" visa_name = "VI_ATTR_ASRL_REPLACE_CHAR" visa_type = "ViUInt8" default = 0 read, write, local = True, True, True class AttrVI_ATTR_ASRL_XOFF_CHAR(CharAttribute): """XOFF character used for XON/XOFF flow control (both directions). If XON/XOFF flow control (software handshaking) is not being used, the value of this attribute is ignored. """ resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "xoff_char" visa_name = "VI_ATTR_ASRL_XOFF_CHAR" visa_type = "ViUInt8" default = 0x13 read, write, local = True, True, True class AttrVI_ATTR_ASRL_XON_CHAR(CharAttribute): """XON character used for XON/XOFF flow control (both directions). If XON/XOFF flow control (software handshaking) is not being used, the value of this attribute is ignored. """ resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "xon_char" visa_name = "VI_ATTR_ASRL_XON_CHAR" visa_type = "ViUInt8" default = 0x11 read, write, local = True, True, True class AttrVI_ATTR_ASRL_CTS_STATE(EnumAttribute): """Current state of the Clear To Send (CTS) input signal.""" resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "" visa_name = "VI_ATTR_ASRL_CTS_STATE" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False enum_type = constants.LineState class AttrVI_ATTR_ASRL_DSR_STATE(EnumAttribute): """Current state of the Data Set Ready (DSR) input signal.""" resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "" visa_name = "VI_ATTR_ASRL_DSR_STATE" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False enum_type = constants.LineState class AttrVI_ATTR_ASRL_DTR_STATE(EnumAttribute): """Current state of the Data Terminal Ready (DTR) input signal.""" resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "" visa_name = "VI_ATTR_ASRL_DTR_STATE" visa_type = "ViInt16" default = NotAvailable read, write, local = True, True, False enum_type = constants.LineState class AttrVI_ATTR_ASRL_RTS_STATE(EnumAttribute): """Manually assert or unassert the Request To Send (RTS) output signal.""" resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "" visa_name = "VI_ATTR_ASRL_RTS_STATE" visa_type = "ViInt16" default = NotAvailable read, write, local = True, True, False enum_type = constants.LineState class AttrVI_ATTR_ASRL_WIRE_MODE(EnumAttribute): """Current wire/transceiver mode. For RS-485 hardware, this attribute is valid only with the RS-485 serial driver developed by National Instruments. For RS-232 hardware, the values RS232/DCE and RS232/AUTO are valid only with RS-232 serial drivers developed by National Instruments and documented to support this feature with the corresponding National Instruments hardware. When this feature is not supported, RS232/DTE is the only valid value. """ resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "" visa_name = "VI_ATTR_ASRL_WIRE_MODE" visa_type = "ViInt16" default = NotAvailable read, write, local = True, True, False enum_type = constants.WireMode class AttrVI_ATTR_ASRL_DCD_STATE(EnumAttribute): """Current state of the Data Carrier Detect (DCD) input signal. The DCD signal is often used by modems to indicate the detection of a carrier (remote modem) on the telephone line. The DCD signal is also known as Receive Line Signal Detect (RLSD). This attribute is Read Only except when the VI_ATTR_ASRL_WIRE_MODE attribute is set to VI_ASRL_WIRE_232_DCE, or VI_ASRL_WIRE_232_AUTO with the hardware currently in the DCE state. """ resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "" visa_name = "VI_ATTR_ASRL_DCD_STATE" visa_type = "ViInt16" default = NotAvailable read, write, local = True, True, False enum_type = constants.LineState class AttrVI_ATTR_ASRL_RI_STATE(EnumAttribute): """Current state of the Ring Indicator (RI) input signal. The RI signal is often used by modems to indicate that the telephone line is ringing. This attribute is Read Only except when the VI_ATTR_ASRL_WIRE_MODE attribute is set to VI_ASRL_WIRE_232_DCE, or VI_ASRL_WIRE_232_AUTO with the hardware currently in the DCE state. """ resources = [(constants.InterfaceType.asrl, "INSTR")] py_name = "" visa_name = "VI_ATTR_ASRL_RI_STATE" visa_type = "ViInt16" default = NotAvailable read, write, local = True, True, False enum_type = constants.LineState class AttrVI_ATTR_USB_INTFC_NUM(RangeAttribute): """USB interface number used by the given session.""" resources = [ (constants.InterfaceType.usb, "INSTR"), (constants.InterfaceType.usb, "RAW"), ] py_name = "interface_number" visa_name = "VI_ATTR_USB_INTFC_NUM" visa_type = "ViInt16" default = 0 read, write, local = True, False, False min_value, max_value, values = 0, 0xFE, None class AttrVI_ATTR_USB_SERIAL_NUM(Attribute): """USB serial number of this device.""" resources = [ (constants.InterfaceType.usb, "INSTR"), (constants.InterfaceType.usb, "RAW"), ] py_name = "serial_number" visa_name = "VI_ATTR_USB_SERIAL_NUM" visa_type = "ViString" default = NotAvailable read, write, local = True, False, False class AttrVI_ATTR_USB_PROTOCOL(RangeAttribute): """USB protocol used by this USB interface.""" resources = [ (constants.InterfaceType.usb, "INSTR"), (constants.InterfaceType.usb, "RAW"), ] py_name = "usb_protocol" visa_name = "VI_ATTR_USB_PROTOCOL" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 0, 0xFF, None class AttrVI_ATTR_USB_MAX_INTR_SIZE(RangeAttribute): """Maximum size of data that will be stored by any given USB interrupt. If a USB interrupt contains more data than this size, the data in excess of this size will be lost. """ resources = [ (constants.InterfaceType.usb, "INSTR"), (constants.InterfaceType.usb, "RAW"), ] py_name = "maximum_interrupt_size" visa_name = "VI_ATTR_USB_MAX_INTR_SIZE" visa_type = "ViUInt16" default = NotAvailable read, write, local = True, True, True min_value, max_value, values = 0, 0xFFFF, None class AttrVI_ATTR_USB_CLASS(RangeAttribute): """USB class used by this USB interface.""" resources = [(constants.InterfaceType.usb, "RAW")] py_name = "" visa_name = "VI_ATTR_USB_CLASS" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 0, 0xFF, None class AttrVI_ATTR_USB_SUBCLASS(RangeAttribute): """USB subclass used by this USB interface.""" resources = [(constants.InterfaceType.usb, "RAW")] py_name = "" visa_name = "VI_ATTR_USB_SUBCLASS" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 0, 0xFF, None class AttrVI_ATTR_USB_BULK_IN_STATUS(RangeAttribute): """Status of the USB bulk-in pipe used by the given session is stalled or ready. This attribute can be set to only VI_USB_PIPE_READY. """ resources = [(constants.InterfaceType.usb, "RAW")] py_name = "" visa_name = "VI_ATTR_USB_BULK_IN_STATUS" visa_type = "ViInt16" default = NotAvailable read, write, local = True, True, True min_value, max_value, values = -32768, 32767, None class AttrVI_ATTR_USB_BULK_IN_PIPE(RangeAttribute): """Endpoint address of the USB bulk-in pipe used by the given session. An initial value of -1 signifies that this resource does not have any bulk-in pipes. This endpoint is used in viRead and related operations. """ resources = [(constants.InterfaceType.usb, "RAW")] py_name = "" visa_name = "VI_ATTR_USB_BULK_IN_PIPE" visa_type = "ViInt16" default = NotAvailable read, write, local = True, True, True min_value, max_value, values = 0x81, 0x8F, [-1] class AttrVI_ATTR_USB_BULK_OUT_STATUS(RangeAttribute): """Status of the USB bulk-out or interrupt-out pipe used by the given session. The status can be stalled or ready. This attribute can be set to only VI_USB_PIPE_READY. """ resources = [(constants.InterfaceType.usb, "RAW")] py_name = "" visa_name = "VI_ATTR_USB_BULK_OUT_STATUS" visa_type = "ViInt16" default = NotAvailable read, write, local = True, True, True min_value, max_value, values = -32768, 32767, None class AttrVI_ATTR_USB_BULK_OUT_PIPE(RangeAttribute): """Endpoint address of the USB bulk-out or interrupt-out pipe. An initial value of –1 signifies that this resource does not have any bulk-out or interrupt-out pipes. This endpoint is used in viWrite and related operations. """ resources = [(constants.InterfaceType.usb, "RAW")] py_name = "" visa_name = "VI_ATTR_USB_BULK_OUT_PIPE" visa_type = "ViInt16" default = NotAvailable read, write, local = True, True, True min_value, max_value, values = 0x01, 0x0F, [-1] class AttrVI_ATTR_USB_INTR_IN_PIPE(RangeAttribute): """Endpoint address of the USB interrupt-in pipe used by the given session. An initial value of -1 signifies that this resource does not have any interrupt-in pipes. This endpoint is used in viEnableEvent for VI_EVENT_USB_INTR. """ resources = [(constants.InterfaceType.usb, "RAW")] py_name = "" visa_name = "VI_ATTR_USB_INTR_IN_PIPE" visa_type = "ViInt16" default = NotAvailable read, write, local = True, True, True min_value, max_value, values = 0x81, 0x8F, [-1] class AttrVI_ATTR_USB_ALT_SETTING(RangeAttribute): """USB alternate setting used by this USB interface.""" resources = [(constants.InterfaceType.usb, "RAW")] py_name = "" visa_name = "VI_ATTR_USB_ALT_SETTING" visa_type = "ViInt16" default = 0 read, write, local = True, True, False min_value, max_value, values = 0, 0xFF, None class AttrVI_ATTR_USB_END_IN(EnumAttribute): """Method used to terminate read operations.""" resources = [(constants.InterfaceType.usb, "RAW")] py_name = "" visa_name = "VI_ATTR_USB_END_IN" visa_type = "ViUInt16" default = constants.VI_USB_END_SHORT_OR_COUNT read, write, local = True, True, True enum_type = constants.USBEndInput class AttrVI_ATTR_USB_NUM_INTFCS(RangeAttribute): """Number of interfaces supported by this USB device.""" resources = [(constants.InterfaceType.usb, "RAW")] py_name = "" visa_name = "VI_ATTR_USB_NUM_INTFCS" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 1, 0xFF, None class AttrVI_ATTR_USB_NUM_PIPES(RangeAttribute): """Number of pipes supported by this USB interface. This does not include the default control pipe. """ resources = [(constants.InterfaceType.usb, "RAW")] py_name = "" visa_name = "VI_ATTR_USB_NUM_PIPES" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 0, 30, None class AttrVI_ATTR_USB_INTR_IN_STATUS(RangeAttribute): """Whether the USB interrupt-in pipe used by the given session is stalled or ready. This attribute can be set to only VI_USB_PIPE_READY. """ resources = [(constants.InterfaceType.usb, "RAW")] py_name = "" visa_name = "VI_ATTR_USB_INTR_IN_STATUS" visa_type = "ViInt16" default = NotAvailable read, write, local = True, True, True min_value, max_value, values = -32768, 32767, None class AttrVI_ATTR_USB_CTRL_PIPE(RangeAttribute): """Endpoint address of the USB control pipe used by the given session. A value of 0 signifies that the default control pipe will be used. This endpoint is used in viUsbControlIn and viUsbControlOut operations. Nonzero values may not be supported on all platforms. """ resources = [(constants.InterfaceType.usb, "RAW")] py_name = "" visa_name = "VI_ATTR_USB_CTRL_PIPE" visa_type = "ViInt16" default = 0x00 read, write, local = True, True, True min_value, max_value, values = 0x00, 0x0F, None class AttrVI_ATTR_MANF_NAME(Attribute): """Manufacturer name.""" resources = [ (constants.InterfaceType.pxi, "INSTR"), (constants.InterfaceType.pxi, "BACKPLANE"), (constants.InterfaceType.usb, "INSTR"), (constants.InterfaceType.usb, "RAW"), (constants.InterfaceType.vxi, "INSTR"), ] py_name = "manufacturer_name" visa_name = "VI_ATTR_MANF_NAME" visa_type = "ViString" default = NotAvailable read, write, local = True, False, False class AttrVI_ATTR_MANF_ID(RangeAttribute): """Manufacturer identification number of the device.""" resources = [ (constants.InterfaceType.pxi, "INSTR"), (constants.InterfaceType.usb, "INSTR"), (constants.InterfaceType.usb, "RAW"), (constants.InterfaceType.vxi, "INSTR"), ] py_name = "manufacturer_id" visa_name = "VI_ATTR_MANF_ID" visa_type = "ViUInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 0x0, 0xFFFF, None class AttrVI_ATTR_MODEL_NAME(Attribute): """Model name of the device.""" resources = [ (constants.InterfaceType.pxi, "INSTR"), (constants.InterfaceType.pxi, "BACKPLANE"), (constants.InterfaceType.usb, "INSTR"), (constants.InterfaceType.usb, "RAW"), (constants.InterfaceType.vxi, "INSTR"), ] py_name = "model_name" visa_name = "VI_ATTR_MODEL_NAME" visa_type = "ViString" default = NotAvailable read, write, local = True, False, False class AttrVI_ATTR_MODEL_CODE(RangeAttribute): """Model code for the device.""" resources = [ (constants.InterfaceType.pxi, "INSTR"), (constants.InterfaceType.usb, "INSTR"), (constants.InterfaceType.usb, "RAW"), (constants.InterfaceType.vxi, "INSTR"), ] py_name = "model_code" visa_name = "VI_ATTR_MODEL_CODE" visa_type = "ViUInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 0x0, 0xFFFF, None class AttrVI_ATTR_DEV_STATUS_BYTE(CharAttribute): """488-style status byte of the local controller or device for this session.""" resources = [ (constants.InterfaceType.gpib, "INTFC"), (constants.InterfaceType.vxi, "SERVANT"), ] py_name = "" visa_name = "VI_ATTR_DEV_STATUS_BYTE" visa_type = "ViUInt8" default = NotAvailable read, write, local = True, True, False class AttrVI_ATTR_4882_COMPLIANT(BooleanAttribute): """Whether the device is 488.2 compliant.""" resources = [ (constants.InterfaceType.usb, "INSTR"), (constants.InterfaceType.vxi, "INSTR"), ] py_name = "is_4882_compliant" visa_name = "VI_ATTR_4882_COMPLIANT" visa_type = "ViBoolean" default = NotAvailable read, write, local = True, False, False class AttrVI_ATTR_SLOT(RangeAttribute): """Physical slot location of the device. If the slot number is not known, VI_UNKNOWN_SLOT is returned. For VXI resources the maximum value is 12, 18 is the maximum for PXI resources. """ resources = [ (constants.InterfaceType.pxi, "INSTR"), (constants.InterfaceType.vxi, "INSTR"), ] py_name = "" visa_name = "VI_ATTR_SLOT" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 1, 18, [constants.VI_UNKNOWN_SLOT] class AttrVI_ATTR_WIN_ACCESS(RangeAttribute): """Modes in which the current window may be accessed.""" resources = [ (constants.InterfaceType.pxi, "INSTR"), (constants.InterfaceType.pxi, "MEMACC"), (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "MEMACC"), ] py_name = "" visa_name = "VI_ATTR_WIN_ACCESS" visa_type = "ViUInt16" default = constants.VI_NMAPPED read, write, local = True, False, True min_value, max_value, values = 0, 65535, None class AttrVI_ATTR_WIN_BASE_ADDR(RangeAttribute): """Base address of the interface bus to which this window is mapped.""" resources = [ (constants.InterfaceType.pxi, "INSTR"), (constants.InterfaceType.pxi, "MEMACC"), (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "MEMACC"), ] py_name = "" visa_name = "VI_ATTR_WIN_BASE_ADDR" visa_type = "ViBusAddress64" if constants.is_64bits else "ViBusAddress" default = NotAvailable read, write, local = True, False, True min_value, max_value, values = ( 0, 0xFFFFFFFFFFFFFFFF if constants.is_64bits else 0xFFFFFFFF, None, ) class AttrVI_ATTR_WIN_SIZE(RangeAttribute): """Base address of the interface bus to which this window is mapped.""" resources = [ (constants.InterfaceType.pxi, "INSTR"), (constants.InterfaceType.pxi, "MEMACC"), (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "MEMACC"), ] py_name = "" visa_name = "VI_ATTR_WIN_SIZE" visa_type = "ViBusSize64" if constants.is_64bits else "ViBusSize" default = NotAvailable read, write, local = True, False, True min_value, max_value, values = ( 0, 0xFFFFFFFFFFFFFFFF if constants.is_64bits else 0xFFFFFFFF, None, ) class AttrVI_ATTR_SRC_INCREMENT(RangeAttribute): """Number of elements by which to increment the source offset after a transfer. The default value of this attribute is 1 (that is, the source address will be incremented by 1 after each transfer), and the viMoveInXX() operations move from consecutive elements. If this attribute is set to 0, the viMoveInXX() operations will always read from the same element, essentially treating the source as a FIFO register. """ resources = [ (constants.InterfaceType.pxi, "INSTR"), (constants.InterfaceType.pxi, "MEMACC"), (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "MEMACC"), ] py_name = "source_increment" visa_name = "VI_ATTR_SRC_INCREMENT" visa_type = "ViInt32" default = 1 read, write, local = True, True, True min_value, max_value, values = 0, 1, None class AttrVI_ATTR_DEST_INCREMENT(RangeAttribute): """Number of elements by which to increment the destination offset after a transfer. The default value of this attribute is 1 (that is, the destination address will be incremented by 1 after each transfer), and the viMoveOutXX() operations move into consecutive elements. If this attribute is set to 0, the viMoveOutXX() operations will always write to the same element, essentially treating the destination as a FIFO register. """ resources = [ (constants.InterfaceType.pxi, "INSTR"), (constants.InterfaceType.pxi, "MEMACC"), (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "MEMACC"), ] py_name = "destination_increment" visa_name = "VI_ATTR_DEST_INCREMENT" visa_type = "ViInt32" default = 1 read, write, local = True, True, True min_value, max_value, values = 0, 1, None class AttrVI_ATTR_FDC_CHNL(RangeAttribute): """Which Fast Data Channel (FDC) to use to transfer the buffer.""" resources = [(constants.InterfaceType.vxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_FDC_CHNL" visa_type = "ViUInt16" default = NotAvailable read, write, local = True, True, True min_value, max_value, values = 0, 7, None class AttrVI_ATTR_FDC_MODE(RangeAttribute): """Which Fast Data Channel (FDC) mode to use (either normal or stream mode).""" resources = [(constants.InterfaceType.vxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_FDC_MODE" visa_type = "ViUInt16" default = constants.VI_FDC_NORMAL read, write, local = True, True, True min_value, max_value, values = 0, 65535, None class AttrVVI_ATTR_FDC_GEN_SIGNAL_EN(BooleanAttribute): """Fast Data Channel (FDC) signal enable.""" resources = [(constants.InterfaceType.vxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_FDC_GEN_SIGNAL_EN" visa_type = "ViBool" default = NotAvailable read, write, local = True, True, True class AttrVI_ATTR_FDC_USE_PAIR(BooleanAttribute): """Use a channel pair for transferring data. If set to False, only one channel will be used. """ resources = [(constants.InterfaceType.vxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_FDC_USE_PAIR" visa_type = "ViBoolean" default = False read, write, local = True, True, True class AttrVI_ATTR_MAINFRAME_LA(RangeAttribute): """Lowest logical address in the mainframe. If the logical address is not known, VI_UNKNOWN_LA is returned. """ resources = [ (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "BACKPLANE"), ] py_name = "" visa_name = "VI_ATTR_MAINFRAME_LA" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 0, 255, [constants.VI_UNKNOWN_LA] class AttrVI_ATTR_VXI_LA(RangeAttribute): """Logical address of the VXI or VME device. For a MEMACC or SERVANT session, this attribute specifies the logical address of the local controller. """ resources = [ (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "MEMACC"), (constants.InterfaceType.vxi, "SERVANT"), ] py_name = "" visa_name = "VI_ATTR_VXI_LA" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 0, 511, None class AttrVI_ATTR_CMDR_LA(RangeAttribute): """Unique logical address of the commander of the VXI device.""" resources = [ (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "SERVANT"), ] py_name = "" visa_name = "VI_ATTR_CMDR_LA" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 0, 255, [constants.VI_UNKNOWN_LA] class AttrVI_ATTR_MEM_SPACE(EnumAttribute): """VI_ATTR_MEM_SPACE specifies the VXIbus address space used by the device. The four types are A16, A24, A32 or A64 memory address space. """ resources = [(constants.InterfaceType.vxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_MEM_SPACE" visa_type = "ViUInt16" default = constants.VI_A16_SPACE read, write, local = True, False, False enum_type = constants.AddressSpace class AttrVI_ATTR_MEM_SIZE(RangeAttribute): """Unique logical address of the commander of the VXI device.""" resources = [ (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "SERVANT"), ] py_name = "" visa_name = "VI_ATTR_MEM_SIZE" visa_type = "ViBusSize64" if constants.is_64bits else "ViUInt32" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = ( 0, 0xFFFFFFFFFFFFFFFF if constants.is_64bits else 0xFFFFFFFF, None, ) class AttrVI_ATTR_MEM_BASE(RangeAttribute): """Unique logical address of the commander of the VXI device.""" resources = [ (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "SERVANT"), ] py_name = "" visa_name = "VI_ATTR_MEM_BASE" visa_type = "ViBusAddress64" if constants.is_64bits else "ViUInt32" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = ( 0, 0xFFFFFFFFFFFFFFFF if constants.is_64bits else 0xFFFFFFFF, None, ) class AttrVI_ATTR_IMMEDIATE_SERV(BooleanAttribute): """Is the device an immediate servant of the controller running VISA.""" resources = [(constants.InterfaceType.vxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_IMMEDIATE_SERV" visa_type = "ViBoolean" default = NotAvailable read, write, local = True, False, False class AttrVI_ATTR_DEST_ACCESS_PRIV(RangeAttribute): """Address modifier to be used in high-level write operations. High level operations are viOutXX() and viMoveOutXX(). """ resources = [ (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "MEMACC"), ] py_name = "" visa_name = "VI_ATTR_DEST_ACCESS_PRIV" visa_type = "ViUInt16" default = constants.VI_DATA_PRIV read, write, local = True, True, True min_value, max_value, values = 0, 65535, None class AttrVI_ATTR_DEST_BYTE_ORDER(EnumAttribute): """Byte order to be used in high-level write operations. High level operations are viOutXX() and viMoveOutXX(). """ resources = [ (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "MEMACC"), ] py_name = "" visa_name = "VI_ATTR_DEST_BYTE_ORDER" visa_type = "ViUInt16" default = constants.VI_BIG_ENDIAN read, write, local = True, True, True enum_type = constants.ByteOrder class AttrVI_ATTR_SRC_ACCESS_PRIV(EnumAttribute): """Address modifier to be used in high-level read operations. High level operations are viInXX() and viMoveinXX(). """ resources = [ (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "MEMACC"), ] py_name = "" visa_name = "VI_ATTR_SRC_ACCESS_PRIV" visa_type = "ViUInt16" default = constants.VI_DATA_PRIV read, write, local = True, True, True enum_type = constants.AddressModifiers class AttrVI_ATTR_SRC_BYTE_ORDER(EnumAttribute): """Byte order to be used in high-level read operations. High level operations are viOutXX() and viMoveOutXX(). """ resources = [ (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "MEMACC"), ] py_name = "" visa_name = "VI_ATTR_SRC_BYTE_ORDER" visa_type = "ViUInt16" default = constants.VI_BIG_ENDIAN read, write, local = True, True, True enum_type = constants.ByteOrder class AttrVI_ATTR_WIN_ACCESS_PRIV(EnumAttribute): """Address modifier to be used in low-level access operations. Low-level operation are viMapAddress(), viPeekXX(), and viPokeXX(), when accessing the mapped window. """ resources = [ (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "MEMACC"), ] py_name = "" visa_name = "VI_ATTR_WIN_ACCESS_PRIV" visa_type = "ViUInt16" default = constants.VI_DATA_PRIV read, write, local = True, True, True enum_type = constants.AddressModifiers class AttrVI_ATTR_WIN_BYTE_ORDER(EnumAttribute): """Byte order to be used in low- level access operations. Low-level operation are viMapAddress(), viPeekXX(), and viPokeXX(), when accessing the mapped window. """ resources = [ (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "MEMACC"), ] py_name = "" visa_name = "VI_ATTR_WIN_BYTE_ORDER" visa_type = "ViUInt16" default = constants.VI_BIG_ENDIAN read, write, local = True, True, True enum_type = constants.ByteOrder class AttrVI_ATTR_VXI_TRIG_SUPPORT(RangeAttribute): """VXI trigger lines this implementation supports. This is a bit vector. Bits 0-7 correspond to VI_TRIG_TTL0 to VI_TRIG_TTL7. Bits 8-13 correspond to VI_TRIG_ECL0 to VI_TRIG_ECL5. Bits 14-25 correspond to VI_TRIG_STAR_SLOT1 to VI_TRIG_STAR_SLOT12. Bit 27 corresponds to VI_TRIG_PANEL_IN and bit 28 corresponds to VI_TRIG_PANEL_OUT. Bits 29-31 correspond to VI_TRIG_STAR_VXI0 to VI_TRIG_STAR_VXI2. VXI does not use VI_TRIG_TTL8 to VI_TRIG_TTL11. """ resources = [ (constants.InterfaceType.vxi, "INSTR"), (constants.InterfaceType.vxi, "BACKPLANE"), ] py_name = "" visa_name = "VI_ATTR_VXI_TRIG_SUPPORT" visa_type = "ViUInt32" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 0, 4294967295, None # GPIB-VXI is not supported # class AttrVI_ATTR_INTF_PARENT_NUM(RangeAttribute): # """This attribute shows the current state of the VXI/VME interrupt lines. # This is a bit vector with bits 0-6 corresponding to interrupt # lines 1-7. # """ # resources = [(constants.InterfaceType.vxi, "BACKPLANE")] # py_name = "" # visa_name = "VI_ATTR_INTF_PARENT_NUM" # visa_type = "ViUInt16" # default = NotAvailable # read, write, local = True, False, False # min_value, max_value, values = 0, 65535, None class AttrVI_ATTR_VXI_DEV_CLASS(EnumAttribute): """VXI-defined device class to which the resource belongs. This can be either: - message based (VI_VXI_CLASS_MESSAGE) - register based (VI_VXI_CLASS_REGISTER) - extended (VI_VXI_CLASS_EXTENDED) - memory (VI_VXI_CLASS_MEMORY) - other (VI_VXI_CLASS_OTHER) VME devices are usually either register based or belong to a miscellaneous class (VI_VXI_CLASS_OTHER). """ resources = [(constants.InterfaceType.vxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_VXI_DEV_CLASS" visa_type = "ViUInt16" default = NotAvailable read, write, local = True, False, False enum_type = constants.VXIClass class AttrVI_ATTR_VXI_TRIG_DIR(RangeAttribute): """Bit map of the directions of the mapped TTL trigger lines. Bits 0-7 represent TTL triggers 0-7 respectively. A bit's value of 0 means the line is routed out of the frame, and a value of 1 means into the frame. In order for a direction to be set, the line must also be enabled using VI_ATTR_VXI_TRIG_LINES_EN. """ resources = [(constants.InterfaceType.vxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_VXI_TRIG_DIR" visa_type = "ViUInt16" default = 0 read, write, local = True, True, False min_value, max_value, values = 0, 65535, None class AttrVI_ATTR_VXI_TRIG_LINES_EN(RangeAttribute): """Bit map of what VXI TLL triggers have mappings. Bits 0-7 represent TTL triggers 0-7 respectively. A bit's value of 0 means the trigger line is unmapped, and 1 means a mapping exists. Use VI_ATTR_VXI_TRIG_DIR to set an enabled line's direction. """ resources = [(constants.InterfaceType.vxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_VXI_TRIG_LINES_EN" visa_type = "ViUInt16" default = 0 read, write, local = True, True, False min_value, max_value, values = 0, 65535, None class AttrVI_ATTR_VXI_VME_INTR_STATUS(RangeAttribute): """Current state of the VXI/VME interrupt lines. This is a bit vector with bits 0-6 corresponding to interrupt lines 1-7. """ resources = [(constants.InterfaceType.vxi, "BACKPLANE")] py_name = "" visa_name = "VI_ATTR_VXI_VME_INTR_STATUS" visa_type = "ViUInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 0, 65535, None class AttrVI_ATTR_VXI_TRIG_STATUS(RangeAttribute): """Current state of the VXI trigger lines. This is a bit vector with bits 0-9 corresponding to VI_TRIG_TTL0 through VI_TRIG_ECL1. """ resources = [(constants.InterfaceType.vxi, "BACKPLANE")] py_name = "" visa_name = "VI_ATTR_VXI_TRIG_STATUS" visa_type = "ViUInt32" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 0, 4294967295, None class AttrVI_ATTR_VXI_VME_SYSFAIL_STATE(EnumAttribute): """Current state of the VXI/VME SYSFAIL (SYStem FAILure) backplane line.""" resources = [(constants.InterfaceType.vxi, "BACKPLANE")] py_name = "" visa_name = "VI_ATTR_VXI_VME_SYSFAIL_STATE" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False enum_type = constants.LineState class AttrVI_ATTR_PXI_DEV_NUM(RangeAttribute): """PXI device number.""" resources = [(constants.InterfaceType.pxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_PXI_DEV_NUM" visa_type = "ViUInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 0, 31, None class AttrVI_ATTR_PXI_FUNC_NUM(RangeAttribute): """PCI function number of the PXI/PCI resource. For most devices, the function number is 0, but a multifunction device may have a function number up to 7. The meaning of a function number other than 0 is device specific. """ resources = [(constants.InterfaceType.pxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_PXI_FUNC_NUM" visa_type = "ViUInt16" default = 0 read, write, local = True, False, False min_value, max_value, values = 0, 7, None class AttrVI_ATTR_PXI_BUS_NUM(RangeAttribute): """PCI bus number of this device.""" resources = [(constants.InterfaceType.pxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_PXI_BUS_NUM" visa_type = "ViUInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 0, 255, None class AttrVI_ATTR_PXI_CHASSIS(RangeAttribute): """PXI chassis number of this device. A value of –1 means the chassis number is unknown. """ resources = [ (constants.InterfaceType.pxi, "INSTR"), (constants.InterfaceType.pxi, "BACKPLANE"), ] py_name = "" visa_name = "VI_ATTR_PXI_CHASSIS" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 0, 255, [-1] class AttrVI_ATTR_PXI_SLOTPATH(Attribute): """Slot path of this device.""" resources = [(constants.InterfaceType.pxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_PXI_SLOTPATH" visa_type = "ViString" default = NotAvailable read, write, local = True, False, False class AttrVI_ATTR_PXI_SLOT_LBUS_LEFT(RangeAttribute): """Slot number or special feature connected to the local bus left lines.""" resources = [(constants.InterfaceType.pxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_PXI_SLOT_LBUS_LEFT" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = ( 1, 18, [ constants.VI_PXI_LBUS_UNKNOWN, constants.VI_PXI_LBUS_NONE, constants.VI_PXI_LBUS_STAR_TRIG_BUS_0, constants.VI_PXI_LBUS_STAR_TRIG_BUS_1, constants.VI_PXI_LBUS_STAR_TRIG_BUS_2, constants.VI_PXI_LBUS_STAR_TRIG_BUS_3, constants.VI_PXI_LBUS_STAR_TRIG_BUS_4, constants.VI_PXI_LBUS_STAR_TRIG_BUS_5, constants.VI_PXI_LBUS_STAR_TRIG_BUS_6, constants.VI_PXI_LBUS_STAR_TRIG_BUS_7, constants.VI_PXI_LBUS_STAR_TRIG_BUS_8, constants.VI_PXI_LBUS_STAR_TRIG_BUS_9, constants.VI_PXI_STAR_TRIG_CONTROLLER, constants.VI_PXI_LBUS_SCXI, ], ) class AttrVI_ATTR_PXI_SLOT_LBUS_RIGHT(RangeAttribute): """Slot number or special feature connected to the local bus right lines.""" resources = [(constants.InterfaceType.pxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_PXI_SLOT_LBUS_RIGHT" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = ( 1, 18, [ constants.VI_PXI_LBUS_UNKNOWN, constants.VI_PXI_LBUS_NONE, constants.VI_PXI_LBUS_STAR_TRIG_BUS_0, constants.VI_PXI_LBUS_STAR_TRIG_BUS_1, constants.VI_PXI_LBUS_STAR_TRIG_BUS_2, constants.VI_PXI_LBUS_STAR_TRIG_BUS_3, constants.VI_PXI_LBUS_STAR_TRIG_BUS_4, constants.VI_PXI_LBUS_STAR_TRIG_BUS_5, constants.VI_PXI_LBUS_STAR_TRIG_BUS_6, constants.VI_PXI_LBUS_STAR_TRIG_BUS_7, constants.VI_PXI_LBUS_STAR_TRIG_BUS_8, constants.VI_PXI_LBUS_STAR_TRIG_BUS_9, constants.VI_PXI_STAR_TRIG_CONTROLLER, constants.VI_PXI_LBUS_SCXI, ], ) class AttrVI_ATTR_PXI_IS_EXPRESS(BooleanAttribute): """Whether the device is PXI/PCI or PXI/PCI Express.""" resources = [(constants.InterfaceType.pxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_PXI_IS_EXPRESS" visa_type = "ViBoolean" default = NotAvailable read, write, local = True, False, False class AttrVI_ATTR_PXI_SLOT_LWIDTH(ValuesAttribute): """PCI Express link width of the PXI Express peripheral slot of the device. A value of –1 indicates that the device is not a PXI Express device. """ resources = [(constants.InterfaceType.pxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_PXI_SLOT_LWIDTH" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False values = [-1, 1, 4, 8] class AttrVI_ATTR_PXI_MAX_LWIDTH(ValuesAttribute): """Maximum PCI Express link width of the device. A value of –1 indicates that the device is not a PXI/PCI Express device. """ resources = [(constants.InterfaceType.pxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_PXI_MAX_LWIDTH" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False values = [-1, 1, 2, 4, 8, 16] class AttrVI_ATTR_PXI_ACTUAL_LWIDTH(ValuesAttribute): """PCI Express link width negotiated between the host controller and the device. A value of –1 indicates that the device is not a PXI/PCI Express device. """ resources = [(constants.InterfaceType.pxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_PXI_ACTUAL_LWIDTH" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False values = [-1, 1, 2, 4, 8, 16] class AttrVI_ATTR_PXI_DSTAR_BUS(RangeAttribute): """Differential star bus number of this device. A value of –1 means the chassis is unidentified or does not have a timing slot. """ resources = [(constants.InterfaceType.pxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_PXI_DSTAR_BUS" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = -32768, 32767, None class AttrVI_ATTR_PXI_DSTAR_SET(RangeAttribute): """Set of PXI_DSTAR lines connected to this device.""" resources = [(constants.InterfaceType.pxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_PXI_DSTAR_SET" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 0, 16, [-1] class AttrVI_ATTR_PXI_TRIG_BUS(RangeAttribute): """The trigger bus number of this device.""" resources = [ (constants.InterfaceType.pxi, "INSTR"), (constants.InterfaceType.pxi, "BACKPLANE"), ] py_name = "" visa_name = "VI_ATTR_PXI_TRIG_BUS" visa_type = "ViInt16" default = NotAvailable read, write, local = True, True, True min_value, max_value, values = 1, 3, [-1] class AttrVI_ATTR_PXI_STAR_TRIG_BUS(RangeAttribute): """The star trigger bus number of this device.""" resources = [(constants.InterfaceType.pxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_PXI_STAR_TRIG_BUS" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 1, 3, [-1] class AttrVI_ATTR_PXI_STAR_TRIG_LINE(RangeAttribute): """The PXI_STAR line connected to this device.""" resources = [(constants.InterfaceType.pxi, "INSTR")] py_name = "" visa_name = "VI_ATTR_PXI_STAR_TRIG_LINE" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 0, 32767, None class AttrVI_ATTR_PXI_SRC_TRIG_BUS(RangeAttribute): """VThe segment to use to qualify trigSrc in viMapTrigger.""" resources = [(constants.InterfaceType.pxi, "BACKPLANE")] py_name = "" visa_name = "VI_ATTR_PXI_SRC_TRIG_BUS" visa_type = "ViInt16" default = -1 read, write, local = True, True, True min_value, max_value, values = 1, 3, [-1] class AttrVI_ATTR_PXI_DEST_TRIG_BUS(RangeAttribute): """The segment to use to qualify trigDest in viMapTrigger.""" resources = [(constants.InterfaceType.pxi, "BACKPLANE")] py_name = "" visa_name = "VI_ATTR_PXI_DEST_TRIG_BUS" visa_type = "ViInt16" default = -1 read, write, local = True, True, True min_value, max_value, values = 1, 3, [-1] class _AttrVI_ATTR_PXI_MEM_TYPE_BARX(EnumAttribute): """Memory type used by the device in the specified BAR (if applicable).""" resources = [(constants.InterfaceType.pxi, "INSTR")] py_name = "" visa_type = "ViUInt16" default = NotAvailable read, write, local = True, False, False enum_type = constants.PXIMemory class _AttrVI_ATTR_PXI_MEM_BASE_BARX(RangeAttribute): """PXI memory base address assigned to the specified BAR. If the value of the corresponding VI_ATTR_PXI_MEM_TYPE_BARx is constants.PXIMemory.none, the value of this attribute is meaningless for the given PXI device. """ resources = [(constants.InterfaceType.pxi, "INSTR")] py_name = "" visa_type = "ViUInt32" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 0, 0xFFFFFFFF, None class _AttrVI_ATTR_PXI_MEM_SIZE_BARX(RangeAttribute): """Memory size used by the device in the specified BAR. If the value of the corresponding VI_ATTR_PXI_MEM_TYPE_BARx is constants.PXIMemory.none, the value of this attribute is meaningless for the given PXI device. """ resources = [(constants.InterfaceType.pxi, "INSTR")] py_name = "" visa_type = "ViUInt32" default = NotAvailable read, write, local = True, False, False min_value, max_value, values = 0, 0xFFFFFFFF, None mod = sys.modules[__name__] for i in range(0, 5): setattr( mod, f"AttrVI_ATTR_PXI_MEM_TYPE_BAR{i}", type( f"AttrVI_ATTR_PXI_MEM_TYPE_BAR{i}", (_AttrVI_ATTR_PXI_MEM_TYPE_BARX,), {"visa_name": f"VI_ATTR_PXI_MEM_TYPE_BAR{i}"}, ), ) setattr( mod, f"AttrVI_ATTR_PXI_MEM_TYPE_BAR{i}", type( f"AttrVI_ATTR_PXI_MEM_BASE_BAR{i}", (_AttrVI_ATTR_PXI_MEM_BASE_BARX,), {"visa_name": f"VI_ATTR_PXI_MEM_BASE_BAR{i}"}, ), ) setattr( mod, f"AttrVI_ATTR_PXI_MEM_TYPE_BAR{i}", type( f"AttrVI_ATTR_PXI_MEM_SIZE_BAR{i}", (_AttrVI_ATTR_PXI_MEM_SIZE_BARX,), {"visa_name": f"VI_ATTR_PXI_MEM_SIZE_BAR{i}"}, ), ) # --- Event type attributes ------------------------------------------------------------ class AttrVI_ATTR_STATUS(EnumAttribute): """Status code of the operation generating this event.""" resources = [constants.EventType.exception, constants.EventType.io_completion] py_name = "status" visa_name = "VI_ATTR_STATUS" visa_type = "ViStatus" default = NotAvailable read, write, local = True, False, True enum_type = constants.StatusCode class AttrVI_ATTR_OPER_NAME(Attribute): """Name of the operation generating this event.""" resources = [constants.EventType.io_completion, constants.EventType.exception] py_name = "operation_name" visa_name = "VI_ATTR_OPER_NAME" visa_type = "ViString" default = NotAvailable read, write, local = True, False, True class AttrVI_ATTR_JOB_ID(Attribute): """Job ID of the asynchronous operation that has completed.""" resources = [constants.EventType.io_completion] py_name = "job_id" visa_name = "VI_ATTR_JOB_ID" visa_type = "ViJobId" default = NotAvailable read, write, local = True, False, True class AttrVI_ATTR_RET_COUNT(RangeAttribute): """Actual number of elements that were asynchronously transferred.""" resources = [constants.EventType.io_completion] py_name = "return_count" visa_name = "VI_ATTR_RET_COUNT" visa_type = "ViUInt32" default = NotAvailable read, write, local = True, False, True min_value, max_value, values = 0, 0xFFFFFFFF, None class AttrVI_ATTR_BUFFER(Attribute): """Buffer that was used in an asynchronous operation.""" resources = [constants.EventType.io_completion] py_name = "buffer" visa_name = "VI_ATTR_BUFFER" visa_type = "ViBuf" default = NotAvailable read, write, local = True, False, True def __get__( # type: ignore self, instance: Optional["IOCompletionEvent"], owner ) -> Optional[Union[SupportsBytes, "AttrVI_ATTR_BUFFER"]]: """Retrieve the buffer stored on the library using the jod Id.""" if instance is None: return self # The buffer we need to access has been created in an earlier call # starting an asynchronous read. When starting that call we stored # the buffer on the resource and we can now retrieve it return instance.visalib.get_buffer_from_id(instance.job_id) class AttrVI_ATTR_RECV_TRIG_ID(EnumAttribute): """Id of the trigger that generated the event.""" resources = [constants.EventType.trig] py_name = "received_trigger_id" visa_name = "VI_ATTR_RECV_TRIG_ID" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, True enum_type = constants.TriggerEventID class AttrVI_ATTR_GPIB_RECV_CIC_STATE(BooleanAttribute): """Whether the event by the gain or the loss of the CIC state.""" resources = [constants.EventType.gpib_controller_in_charge] py_name = "cic_state" visa_name = "VI_ATTR_GPIB_RECV_CIC_STATE" visa_type = "ViBool" default = NotAvailable read, write, local = True, False, True class AttrVI_ATTR_RECV_TCPIP_ADDR(Attribute): """Address of the device from which the session received a connection.""" resources = [constants.EventType.tcpip_connect] py_name = "tcpip_connect" visa_name = "VI_ATTR_RECV_TCPIP_ADDR" visa_type = "ViString" default = NotAvailable read, write, local = True, False, True class AttrVI_ATTR_USB_RECV_INTR_SIZE(RangeAttribute): """Size of the data that was received from the USB interrupt-IN pipe.""" resources = [constants.EventType.usb_interrupt] py_name = "size" visa_name = "VI_ATTR_USB_RECV_INTR_SIZE" visa_type = "ViUInt16" default = NotAvailable read, write, local = True, False, True min_value, max_value, values = 0, 0xFFFF, None class AttrVI_ATTR_USB_RECV_INTR_DATA(Attribute): """Actual data that was received from the USB interrupt-IN pipe.""" resources = [constants.EventType.pxi_interrupt] py_name = "data" visa_name = "VI_ATTR_USB_RECV_INTR_DATA" visa_type = "ViBuf" default = NotAvailable read, write, local = True, False, True class AttrVI_ATTR_SIGP_STATUS_ID(RangeAttribute): """16-bit Status/ID retrieved during the IACK cycle or from the Signal register.""" resources = [constants.EventType.vxi_signal_interrupt] py_name = "signal_register_status_id" visa_name = "VI_ATTR_SIGP_STATUS_ID" visa_type = "ViUInt16" default = NotAvailable read, write, local = True, False, True min_value, max_value, values = 0, 0xFFFF, None class AttrVI_ATTR_INTR_STATUS_ID(RangeAttribute): """32-bit status/ID retrieved during the IACK cycle.""" resources = [constants.EventType.vxi_vme_interrupt] py_name = "status_id" visa_name = "VI_ATTR_INTR_STATUS_ID" visa_type = "ViUInt32" default = NotAvailable read, write, local = True, False, True min_value, max_value, values = 0, 0xFFFFFFFF, None class AttrVI_ATTR_RECV_INTR_LEVEL(RangeAttribute): """VXI interrupt level on which the interrupt was received.""" resources = [constants.EventType.vxi_vme_interrupt] py_name = "level" visa_name = "VI_ATTR_RECV_INTR_LEVEL" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, True min_value, max_value, values = 1, 7, [constants.VI_UNKNOWN_LEVEL] class AttrVI_ATTR_PXI_RECV_INTR_SEQ(Attribute): """Index of the interrupt sequence that detected the interrupt condition.""" resources = [constants.EventType.pxi_interrupt] py_name = "sequence" visa_name = "VI_ATTR_PXI_RECV_INTR_SEQ" visa_type = "ViInt16" default = NotAvailable read, write, local = True, False, True class AttrVI_ATTR_PXI_RECV_INTR_DATA(Attribute): """First PXI/PCI register read in the successful interrupt detection sequence.""" resources = [constants.EventType.pxi_interrupt] py_name = "data" visa_name = "VI_ATTR_PXI_RECV_INTR_DATA" visa_type = "ViUInt32" default = NotAvailable read, write, local = True, False, True pyvisa-1.11.3/pyvisa/cmd_line_tools.py000066400000000000000000000033511375165327600200100ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Command line tools used for debugging and testing. This file is part of PyVISA. :copyright: 2019-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ from typing import Optional def visa_main(command: Optional[str] = None) -> None: """Run the main entry point for command line tools. Parameters ---------- command : str, optional What command to invoke, if None the value is read from the command line arguments """ import argparse parser = argparse.ArgumentParser(description="PyVISA command-line utilities") parser.add_argument( "--backend", "-b", dest="backend", action="store", default=None, help="backend to be used (default: ivi)", ) if not command: subparsers = parser.add_subparsers(title="command", dest="command") subparsers.add_parser("info", help="print information to diagnose PyVISA") subparsers.add_parser("shell", help="start the PyVISA console") args = parser.parse_args() if command: args.command = command if args.command == "info": from pyvisa import util util.get_debug_info() elif args.command == "shell": from pyvisa import shell shell.main("@" + args.backend if args.backend else "") shell.main("@" + args.backend if args.backend else "") else: raise ValueError( f"Unknown command {args.command}. Valid values are: info and shell" ) def visa_shell() -> None: """Run the VISA shell CLI program.""" visa_main("shell") def visa_info() -> None: """Summarize the infos about PyVISA and VISA.""" visa_main("info") pyvisa-1.11.3/pyvisa/constants.py000066400000000000000000002075641375165327600170460ustar00rootroot00000000000000# -*- coding: utf-8 -*- """VISA VPP-4.3 constants (VPP-4.3.2 spec, section 3). Makes all "completion and error codes", "attribute values", "event type values", and "values and ranges" defined in the VISA specification VPP-4.3.2, section 3, available as variable values. The module exports the values under the original, all-uppercase names. This file is part of PyVISA. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ import enum import sys from typing_extensions import Literal is_64bits = sys.maxsize > 2 ** 32 def _to_int(x: int) -> int: """Convert a signed completion and error code to the proper value. This function is necessary because the VISA specification is flawed: It defines the VISA codes, which have a value less than zero, in their internal 32-bit signed integer representation. However, this is positive. ctypes doesn't care about that and (correctly) returns the negative value, which is left as such by Python. Parameters ---------- x : int Value in 32-bit notation as listed in the VPP-4.3.2 specification Returns ------- int Properly signed value """ if x > 0x7FFFFFFF: return int(x - 0x100000000) else: return int(x) # fmt: off # ====================================================================================== # --- VISA constants ------------------------------------------------------------------ # ====================================================================================== # Status codes : success VI_SUCCESS = _to_int(0x00000000) VI_SUCCESS_EVENT_EN = _to_int(0x3FFF0002) VI_SUCCESS_EVENT_DIS = _to_int(0x3FFF0003) VI_SUCCESS_QUEUE_EMPTY = _to_int(0x3FFF0004) VI_SUCCESS_TERM_CHAR = _to_int(0x3FFF0005) VI_SUCCESS_MAX_CNT = _to_int(0x3FFF0006) VI_SUCCESS_DEV_NPRESENT = _to_int(0x3FFF007D) VI_SUCCESS_TRIG_MAPPED = _to_int(0x3FFF007E) VI_SUCCESS_QUEUE_NEMPTY = _to_int(0x3FFF0080) VI_SUCCESS_NCHAIN = _to_int(0x3FFF0098) VI_SUCCESS_NESTED_SHARED = _to_int(0x3FFF0099) VI_SUCCESS_NESTED_EXCLUSIVE = _to_int(0x3FFF009A) VI_SUCCESS_SYNC = _to_int(0x3FFF009B) # Status codes : warning VI_WARN_QUEUE_OVERFLOW = _to_int(0x3FFF000C) VI_WARN_CONFIG_NLOADED = _to_int(0x3FFF0077) VI_WARN_NULL_OBJECT = _to_int(0x3FFF0082) VI_WARN_NSUP_ATTR_STATE = _to_int(0x3FFF0084) VI_WARN_UNKNOWN_STATUS = _to_int(0x3FFF0085) VI_WARN_NSUP_BUF = _to_int(0x3FFF0088) # The following one is a non-standard NI extension VI_WARN_EXT_FUNC_NIMPL = _to_int(0x3FFF00A9) # Status codes : errors VI_ERROR_SYSTEM_ERROR = _to_int(0xBFFF0000) VI_ERROR_INV_OBJECT = _to_int(0xBFFF000E) VI_ERROR_RSRC_LOCKED = _to_int(0xBFFF000F) VI_ERROR_INV_EXPR = _to_int(0xBFFF0010) VI_ERROR_RSRC_NFOUND = _to_int(0xBFFF0011) VI_ERROR_INV_RSRC_NAME = _to_int(0xBFFF0012) VI_ERROR_INV_ACC_MODE = _to_int(0xBFFF0013) VI_ERROR_TMO = _to_int(0xBFFF0015) VI_ERROR_CLOSING_FAILED = _to_int(0xBFFF0016) VI_ERROR_INV_DEGREE = _to_int(0xBFFF001B) VI_ERROR_INV_JOB_ID = _to_int(0xBFFF001C) VI_ERROR_NSUP_ATTR = _to_int(0xBFFF001D) VI_ERROR_NSUP_ATTR_STATE = _to_int(0xBFFF001E) VI_ERROR_ATTR_READONLY = _to_int(0xBFFF001F) VI_ERROR_INV_LOCK_TYPE = _to_int(0xBFFF0020) VI_ERROR_INV_ACCESS_KEY = _to_int(0xBFFF0021) VI_ERROR_INV_EVENT = _to_int(0xBFFF0026) VI_ERROR_INV_MECH = _to_int(0xBFFF0027) VI_ERROR_HNDLR_NINSTALLED = _to_int(0xBFFF0028) VI_ERROR_INV_HNDLR_REF = _to_int(0xBFFF0029) VI_ERROR_INV_CONTEXT = _to_int(0xBFFF002A) VI_ERROR_QUEUE_OVERFLOW = _to_int(0xBFFF002D) VI_ERROR_NENABLED = _to_int(0xBFFF002F) VI_ERROR_ABORT = _to_int(0xBFFF0030) VI_ERROR_RAW_WR_PROT_VIOL = _to_int(0xBFFF0034) VI_ERROR_RAW_RD_PROT_VIOL = _to_int(0xBFFF0035) VI_ERROR_OUTP_PROT_VIOL = _to_int(0xBFFF0036) VI_ERROR_INP_PROT_VIOL = _to_int(0xBFFF0037) VI_ERROR_BERR = _to_int(0xBFFF0038) VI_ERROR_IN_PROGRESS = _to_int(0xBFFF0039) VI_ERROR_INV_SETUP = _to_int(0xBFFF003A) VI_ERROR_QUEUE_ERROR = _to_int(0xBFFF003B) VI_ERROR_ALLOC = _to_int(0xBFFF003C) VI_ERROR_INV_MASK = _to_int(0xBFFF003D) VI_ERROR_IO = _to_int(0xBFFF003E) VI_ERROR_INV_FMT = _to_int(0xBFFF003F) VI_ERROR_NSUP_FMT = _to_int(0xBFFF0041) VI_ERROR_LINE_IN_USE = _to_int(0xBFFF0042) VI_ERROR_NSUP_MODE = _to_int(0xBFFF0046) VI_ERROR_SRQ_NOCCURRED = _to_int(0xBFFF004A) VI_ERROR_INV_SPACE = _to_int(0xBFFF004E) VI_ERROR_INV_OFFSET = _to_int(0xBFFF0051) VI_ERROR_INV_WIDTH = _to_int(0xBFFF0052) VI_ERROR_NSUP_OFFSET = _to_int(0xBFFF0054) VI_ERROR_NSUP_VAR_WIDTH = _to_int(0xBFFF0055) VI_ERROR_WINDOW_NMAPPED = _to_int(0xBFFF0057) VI_ERROR_RESP_PENDING = _to_int(0xBFFF0059) VI_ERROR_NLISTENERS = _to_int(0xBFFF005F) VI_ERROR_NCIC = _to_int(0xBFFF0060) VI_ERROR_NSYS_CNTLR = _to_int(0xBFFF0061) VI_ERROR_NSUP_OPER = _to_int(0xBFFF0067) VI_ERROR_INTR_PENDING = _to_int(0xBFFF0068) VI_ERROR_ASRL_PARITY = _to_int(0xBFFF006A) VI_ERROR_ASRL_FRAMING = _to_int(0xBFFF006B) VI_ERROR_ASRL_OVERRUN = _to_int(0xBFFF006C) VI_ERROR_TRIG_NMAPPED = _to_int(0xBFFF006E) VI_ERROR_NSUP_ALIGN_OFFSET = _to_int(0xBFFF0070) VI_ERROR_USER_BUF = _to_int(0xBFFF0071) VI_ERROR_RSRC_BUSY = _to_int(0xBFFF0072) VI_ERROR_NSUP_WIDTH = _to_int(0xBFFF0076) VI_ERROR_INV_PARAMETER = _to_int(0xBFFF0078) VI_ERROR_INV_PROT = _to_int(0xBFFF0079) VI_ERROR_INV_SIZE = _to_int(0xBFFF007B) VI_ERROR_WINDOW_MAPPED = _to_int(0xBFFF0080) VI_ERROR_NIMPL_OPER = _to_int(0xBFFF0081) VI_ERROR_INV_LENGTH = _to_int(0xBFFF0083) VI_ERROR_INV_MODE = _to_int(0xBFFF0091) VI_ERROR_SESN_NLOCKED = _to_int(0xBFFF009C) VI_ERROR_MEM_NSHARED = _to_int(0xBFFF009D) VI_ERROR_LIBRARY_NFOUND = _to_int(0xBFFF009E) VI_ERROR_NSUP_INTR = _to_int(0xBFFF009F) VI_ERROR_INV_LINE = _to_int(0xBFFF00A0) VI_ERROR_FILE_ACCESS = _to_int(0xBFFF00A1) VI_ERROR_FILE_IO = _to_int(0xBFFF00A2) VI_ERROR_NSUP_LINE = _to_int(0xBFFF00A3) VI_ERROR_NSUP_MECH = _to_int(0xBFFF00A4) VI_ERROR_INTF_NUM_NCONFIG = _to_int(0xBFFF00A5) VI_ERROR_CONN_LOST = _to_int(0xBFFF00A6) # The following two are a non-standard NI extensions VI_ERROR_MACHINE_NAVAIL = _to_int(0xBFFF00A7) VI_ERROR_NPERMISSION = _to_int(0xBFFF00A8) # # Attribute constants # # All attribute codes are unsigned long, so no _to_int() is necessary. # VI_ATTR_RSRC_CLASS = 0xBFFF0001 VI_ATTR_RSRC_NAME = 0xBFFF0002 VI_ATTR_RSRC_IMPL_VERSION = 0x3FFF0003 VI_ATTR_RSRC_LOCK_STATE = 0x3FFF0004 VI_ATTR_MAX_QUEUE_LENGTH = 0x3FFF0005 VI_ATTR_USER_DATA_32 = 0x3FFF0007 VI_ATTR_USER_DATA_64 = 0x3FFF000A VI_ATTR_USER_DATA = ( VI_ATTR_USER_DATA_64 if is_64bits else VI_ATTR_USER_DATA_64 ) VI_ATTR_FDC_CHNL = 0x3FFF000D VI_ATTR_FDC_MODE = 0x3FFF000F VI_ATTR_FDC_GEN_SIGNAL_EN = 0x3FFF0011 VI_ATTR_FDC_USE_PAIR = 0x3FFF0013 VI_ATTR_SEND_END_EN = 0x3FFF0016 VI_ATTR_TERMCHAR = 0x3FFF0018 VI_ATTR_TMO_VALUE = 0x3FFF001A VI_ATTR_GPIB_READDR_EN = 0x3FFF001B VI_ATTR_IO_PROT = 0x3FFF001C VI_ATTR_DMA_ALLOW_EN = 0x3FFF001E VI_ATTR_ASRL_BAUD = 0x3FFF0021 VI_ATTR_ASRL_DATA_BITS = 0x3FFF0022 VI_ATTR_ASRL_PARITY = 0x3FFF0023 VI_ATTR_ASRL_STOP_BITS = 0x3FFF0024 VI_ATTR_ASRL_FLOW_CNTRL = 0x3FFF0025 VI_ATTR_ASRL_DISCARD_NULL = 0x3FFF00B0 VI_ATTR_ASRL_CONNECTED = 0x3FFF01BB VI_ATTR_ASRL_BREAK_STATE = 0x3FFF01BC VI_ATTR_ASRL_BREAK_LEN = 0x3FFF01BD VI_ATTR_ASRL_ALLOW_TRANSMIT = 0x3FFF01BE VI_ATTR_ASRL_WIRE_MODE = 0x3FFF01BF # National instrument only VI_ATTR_RD_BUF_OPER_MODE = 0x3FFF002A VI_ATTR_RD_BUF_SIZE = 0x3FFF002B VI_ATTR_WR_BUF_OPER_MODE = 0x3FFF002D VI_ATTR_WR_BUF_SIZE = 0x3FFF002E VI_ATTR_SUPPRESS_END_EN = 0x3FFF0036 VI_ATTR_TERMCHAR_EN = 0x3FFF0038 VI_ATTR_DEST_ACCESS_PRIV = 0x3FFF0039 VI_ATTR_DEST_BYTE_ORDER = 0x3FFF003A VI_ATTR_SRC_ACCESS_PRIV = 0x3FFF003C VI_ATTR_SRC_BYTE_ORDER = 0x3FFF003D VI_ATTR_SRC_INCREMENT = 0x3FFF0040 VI_ATTR_DEST_INCREMENT = 0x3FFF0041 VI_ATTR_WIN_ACCESS_PRIV = 0x3FFF0045 VI_ATTR_WIN_BYTE_ORDER = 0x3FFF0047 VI_ATTR_GPIB_ATN_STATE = 0x3FFF0057 VI_ATTR_GPIB_ADDR_STATE = 0x3FFF005C VI_ATTR_GPIB_CIC_STATE = 0x3FFF005E VI_ATTR_GPIB_NDAC_STATE = 0x3FFF0062 VI_ATTR_GPIB_SRQ_STATE = 0x3FFF0067 VI_ATTR_GPIB_SYS_CNTRL_STATE = 0x3FFF0068 VI_ATTR_GPIB_HS488_CBL_LEN = 0x3FFF0069 VI_ATTR_CMDR_LA = 0x3FFF006B VI_ATTR_VXI_DEV_CLASS = 0x3FFF006C VI_ATTR_MAINFRAME_LA = 0x3FFF0070 VI_ATTR_MANF_NAME = 0xBFFF0072 VI_ATTR_MODEL_NAME = 0xBFFF0077 VI_ATTR_VXI_VME_INTR_STATUS = 0x3FFF008B VI_ATTR_VXI_TRIG_STATUS = 0x3FFF008D VI_ATTR_VXI_VME_SYSFAIL_STATE = 0x3FFF0094 VI_ATTR_WIN_BASE_ADDR_32 = 0x3FFF0098 VI_ATTR_WIN_BASE_ADDR_64 = 0x3FFF009B VI_ATTR_WIN_BASE_ADDR = ( VI_ATTR_WIN_BASE_ADDR_64 if is_64bits else VI_ATTR_WIN_BASE_ADDR_32 ) VI_ATTR_WIN_SIZE = 0x3FFF009A VI_ATTR_ASRL_AVAIL_NUM = 0x3FFF00AC VI_ATTR_MEM_BASE_32 = 0x3FFF00AD VI_ATTR_MEM_BASE_64 = 0x3FFF00D0 VI_ATTR_MEM_BASE = ( VI_ATTR_MEM_BASE_64 if is_64bits else VI_ATTR_MEM_BASE_32 ) VI_ATTR_ASRL_CTS_STATE = 0x3FFF00AE VI_ATTR_ASRL_DCD_STATE = 0x3FFF00AF VI_ATTR_ASRL_DSR_STATE = 0x3FFF00B1 VI_ATTR_ASRL_DTR_STATE = 0x3FFF00B2 VI_ATTR_ASRL_END_IN = 0x3FFF00B3 VI_ATTR_ASRL_END_OUT = 0x3FFF00B4 VI_ATTR_ASRL_REPLACE_CHAR = 0x3FFF00BE VI_ATTR_ASRL_RI_STATE = 0x3FFF00BF VI_ATTR_ASRL_RTS_STATE = 0x3FFF00C0 VI_ATTR_ASRL_XON_CHAR = 0x3FFF00C1 VI_ATTR_ASRL_XOFF_CHAR = 0x3FFF00C2 VI_ATTR_WIN_ACCESS = 0x3FFF00C3 VI_ATTR_RM_SESSION = 0x3FFF00C4 VI_ATTR_VXI_LA = 0x3FFF00D5 VI_ATTR_MANF_ID = 0x3FFF00D9 VI_ATTR_MEM_SIZE_32 = 0x3FFF00DD VI_ATTR_MEM_SIZE_64 = 0x3FFF00D1 VI_ATTR_MEM_SIZE = ( VI_ATTR_MEM_SIZE_64 if is_64bits else VI_ATTR_MEM_SIZE_32 ) VI_ATTR_MEM_SPACE = 0x3FFF00DE VI_ATTR_MODEL_CODE = 0x3FFF00DF VI_ATTR_SLOT = 0x3FFF00E8 VI_ATTR_INTF_INST_NAME = 0xBFFF00E9 VI_ATTR_IMMEDIATE_SERV = 0x3FFF0100 VI_ATTR_INTF_PARENT_NUM = 0x3FFF0101 VI_ATTR_RSRC_SPEC_VERSION = 0x3FFF0170 VI_ATTR_INTF_TYPE = 0x3FFF0171 VI_ATTR_GPIB_PRIMARY_ADDR = 0x3FFF0172 VI_ATTR_GPIB_SECONDARY_ADDR = 0x3FFF0173 VI_ATTR_RSRC_MANF_NAME = 0xBFFF0174 VI_ATTR_RSRC_MANF_ID = 0x3FFF0175 VI_ATTR_INTF_NUM = 0x3FFF0176 VI_ATTR_TRIG_ID = 0x3FFF0177 VI_ATTR_GPIB_REN_STATE = 0x3FFF0181 VI_ATTR_GPIB_UNADDR_EN = 0x3FFF0184 VI_ATTR_DEV_STATUS_BYTE = 0x3FFF0189 VI_ATTR_FILE_APPEND_EN = 0x3FFF0192 VI_ATTR_VXI_TRIG_SUPPORT = 0x3FFF0194 VI_ATTR_TCPIP_ADDR = 0xBFFF0195 VI_ATTR_TCPIP_HOSTNAME = 0xBFFF0196 VI_ATTR_TCPIP_PORT = 0x3FFF0197 VI_ATTR_TCPIP_DEVICE_NAME = 0xBFFF0199 VI_ATTR_TCPIP_NODELAY = 0x3FFF019A VI_ATTR_TCPIP_KEEPALIVE = 0x3FFF019B VI_ATTR_TCPIP_HISLIP_OVERLAP_EN = 0x3FFF0300 VI_ATTR_TCPIP_HISLIP_VERSION = 0x3FFF0301 VI_ATTR_TCPIP_HISLIP_MAX_MESSAGE_KB = 0x3FFF0302 VI_ATTR_TCPIP_IS_HISLIP = 0x3FFF0303 VI_ATTR_4882_COMPLIANT = 0x3FFF019F VI_ATTR_USB_SERIAL_NUM = 0xBFFF01A0 VI_ATTR_USB_INTFC_NUM = 0x3FFF01A1 VI_ATTR_USB_PROTOCOL = 0x3FFF01A7 VI_ATTR_USB_MAX_INTR_SIZE = 0x3FFF01AF VI_ATTR_USB_BULK_OUT_PIPE = _to_int(0x3FFF01A2) VI_ATTR_USB_BULK_IN_PIPE = _to_int(0x3FFF01A3) VI_ATTR_USB_INTR_IN_PIPE = _to_int(0x3FFF01A4) VI_ATTR_USB_CLASS = _to_int(0x3FFF01A5) VI_ATTR_USB_SUBCLASS = _to_int(0x3FFF01A6) VI_ATTR_USB_ALT_SETTING = _to_int(0x3FFF01A8) VI_ATTR_USB_END_IN = _to_int(0x3FFF01A9) VI_ATTR_USB_NUM_INTFCS = _to_int(0x3FFF01AA) VI_ATTR_USB_NUM_PIPES = _to_int(0x3FFF01AB) VI_ATTR_USB_BULK_OUT_STATUS = _to_int(0x3FFF01AC) VI_ATTR_USB_BULK_IN_STATUS = _to_int(0x3FFF01AD) VI_ATTR_USB_INTR_IN_STATUS = _to_int(0x3FFF01AE) VI_ATTR_USB_CTRL_PIPE = _to_int(0x3FFF01B0) VI_ATTR_USB_RECV_INTR_SIZE = 0x3FFF41B0 VI_ATTR_USB_RECV_INTR_DATA = 0xBFFF41B1 VI_ATTR_JOB_ID = 0x3FFF4006 VI_ATTR_EVENT_TYPE = 0x3FFF4010 VI_ATTR_SIGP_STATUS_ID = 0x3FFF4011 VI_ATTR_RECV_TRIG_ID = 0x3FFF4012 VI_ATTR_INTR_STATUS_ID = 0x3FFF4023 VI_ATTR_STATUS = 0x3FFF4025 VI_ATTR_RET_COUNT_32 = 0x3FFF4026 VI_ATTR_RET_COUNT_64 = 0x3FFF4028 VI_ATTR_RET_COUNT = VI_ATTR_RET_COUNT_64 if is_64bits else VI_ATTR_RET_COUNT_64 VI_ATTR_BUFFER = 0x3FFF4027 VI_ATTR_RECV_INTR_LEVEL = 0x3FFF4041 VI_ATTR_OPER_NAME = 0xBFFF4042 VI_ATTR_GPIB_RECV_CIC_STATE = 0x3FFF4193 VI_ATTR_RECV_TCPIP_ADDR = 0xBFFF4198 VI_ATTR_PXI_DEV_NUM = _to_int(0x3FFF0201) VI_ATTR_PXI_FUNC_NUM = _to_int(0x3FFF0202) VI_ATTR_PXI_BUS_NUM = _to_int(0x3FFF0205) VI_ATTR_PXI_CHASSIS = _to_int(0x3FFF0206) VI_ATTR_PXI_SLOTPATH = _to_int(0xBFFF0207) VI_ATTR_PXI_SLOT_LBUS_LEFT = _to_int(0x3FFF0208) VI_ATTR_PXI_SLOT_LBUS_RIGHT = _to_int(0x3FFF0209) VI_ATTR_PXI_TRIG_BUS = _to_int(0x3FFF020A) VI_ATTR_PXI_STAR_TRIG_BUS = _to_int(0x3FFF020B) VI_ATTR_PXI_STAR_TRIG_LINE = _to_int(0x3FFF020C) VI_ATTR_PXI_IS_EXPRESS = _to_int(0x3FFF0240) VI_ATTR_PXI_SLOT_LWIDTH = _to_int(0x3FFF0241) VI_ATTR_PXI_MAX_LWIDTH = _to_int(0x3FFF0242) VI_ATTR_PXI_ACTUAL_LWIDTH = _to_int(0x3FFF0243) VI_ATTR_PXI_DSTAR_BUS = _to_int(0x3FFF0244) VI_ATTR_PXI_DSTAR_SET = _to_int(0x3FFF0245) VI_ATTR_PXI_SRC_TRIG_BUS = _to_int(0x3FFF020D) VI_ATTR_PXI_DEST_TRIG_BUS = _to_int(0x3FFF020E) VI_ATTR_PXI_RECV_INTR_SEQ = _to_int(0x3FFF4240) VI_ATTR_PXI_RECV_INTR_DATA = _to_int(0x3FFF4241) VI_ATTR_PXI_MEM_TYPE_BAR0 = _to_int(0x3FFF0211) VI_ATTR_PXI_MEM_TYPE_BAR1 = _to_int(0x3FFF0212) VI_ATTR_PXI_MEM_TYPE_BAR2 = _to_int(0x3FFF0213) VI_ATTR_PXI_MEM_TYPE_BAR3 = _to_int(0x3FFF0214) VI_ATTR_PXI_MEM_TYPE_BAR4 = _to_int(0x3FFF0215) VI_ATTR_PXI_MEM_TYPE_BAR5 = _to_int(0x3FFF0216) VI_ATTR_PXI_MEM_BASE_BAR0_32 = _to_int(0x3FFF0221) VI_ATTR_PXI_MEM_BASE_BAR1_32 = _to_int(0x3FFF0222) VI_ATTR_PXI_MEM_BASE_BAR2_32 = _to_int(0x3FFF0223) VI_ATTR_PXI_MEM_BASE_BAR3_32 = _to_int(0x3FFF0224) VI_ATTR_PXI_MEM_BASE_BAR4_32 = _to_int(0x3FFF0225) VI_ATTR_PXI_MEM_BASE_BAR5_32 = _to_int(0x3FFF0226) VI_ATTR_PXI_MEM_SIZE_BAR0_32 = _to_int(0x3FFF0231) VI_ATTR_PXI_MEM_SIZE_BAR1_32 = _to_int(0x3FFF0232) VI_ATTR_PXI_MEM_SIZE_BAR2_32 = _to_int(0x3FFF0233) VI_ATTR_PXI_MEM_SIZE_BAR3_32 = _to_int(0x3FFF0234) VI_ATTR_PXI_MEM_SIZE_BAR4_32 = _to_int(0x3FFF0235) VI_ATTR_PXI_MEM_SIZE_BAR5_32 = _to_int(0x3FFF0236) VI_ATTR_PXI_MEM_BASE_BAR0_64 = _to_int(0x3FFF0228) VI_ATTR_PXI_MEM_BASE_BAR1_64 = _to_int(0x3FFF0229) VI_ATTR_PXI_MEM_BASE_BAR2_64 = _to_int(0x3FFF022A) VI_ATTR_PXI_MEM_BASE_BAR3_64 = _to_int(0x3FFF022B) VI_ATTR_PXI_MEM_BASE_BAR4_64 = _to_int(0x3FFF022C) VI_ATTR_PXI_MEM_BASE_BAR5_64 = _to_int(0x3FFF022D) VI_ATTR_PXI_MEM_SIZE_BAR0_64 = _to_int(0x3FFF0238) VI_ATTR_PXI_MEM_SIZE_BAR1_64 = _to_int(0x3FFF0239) VI_ATTR_PXI_MEM_SIZE_BAR2_64 = _to_int(0x3FFF023A) VI_ATTR_PXI_MEM_SIZE_BAR3_64 = _to_int(0x3FFF023B) VI_ATTR_PXI_MEM_SIZE_BAR4_64 = _to_int(0x3FFF023C) VI_ATTR_PXI_MEM_SIZE_BAR5_64 = _to_int(0x3FFF023D) VI_ATTR_PXI_MEM_BASE_BAR0 = ( VI_ATTR_PXI_MEM_BASE_BAR0_64 if is_64bits else VI_ATTR_PXI_MEM_BASE_BAR0_32 ) VI_ATTR_PXI_MEM_BASE_BAR1 = ( VI_ATTR_PXI_MEM_BASE_BAR1_64 if is_64bits else VI_ATTR_PXI_MEM_BASE_BAR1_32 ) VI_ATTR_PXI_MEM_BASE_BAR2 = ( VI_ATTR_PXI_MEM_BASE_BAR2_64 if is_64bits else VI_ATTR_PXI_MEM_BASE_BAR2_32 ) VI_ATTR_PXI_MEM_BASE_BAR3 = ( VI_ATTR_PXI_MEM_BASE_BAR3_64 if is_64bits else VI_ATTR_PXI_MEM_BASE_BAR3_32 ) VI_ATTR_PXI_MEM_BASE_BAR4 = ( VI_ATTR_PXI_MEM_BASE_BAR4_64 if is_64bits else VI_ATTR_PXI_MEM_BASE_BAR4_32 ) VI_ATTR_PXI_MEM_BASE_BAR5 = ( VI_ATTR_PXI_MEM_BASE_BAR5_64 if is_64bits else VI_ATTR_PXI_MEM_BASE_BAR5_32 ) VI_ATTR_PXI_MEM_SIZE_BAR0 = ( VI_ATTR_PXI_MEM_SIZE_BAR0_64 if is_64bits else VI_ATTR_PXI_MEM_SIZE_BAR0_32 ) VI_ATTR_PXI_MEM_SIZE_BAR1 = ( VI_ATTR_PXI_MEM_SIZE_BAR1_64 if is_64bits else VI_ATTR_PXI_MEM_SIZE_BAR1_32 ) VI_ATTR_PXI_MEM_SIZE_BAR2 = ( VI_ATTR_PXI_MEM_SIZE_BAR2_64 if is_64bits else VI_ATTR_PXI_MEM_SIZE_BAR2_32 ) VI_ATTR_PXI_MEM_SIZE_BAR3 = ( VI_ATTR_PXI_MEM_SIZE_BAR3_64 if is_64bits else VI_ATTR_PXI_MEM_SIZE_BAR3_32 ) VI_ATTR_PXI_MEM_SIZE_BAR4 = ( VI_ATTR_PXI_MEM_SIZE_BAR4_64 if is_64bits else VI_ATTR_PXI_MEM_SIZE_BAR4_32 ) VI_ATTR_PXI_MEM_SIZE_BAR5 = ( VI_ATTR_PXI_MEM_SIZE_BAR5_64 if is_64bits else VI_ATTR_PXI_MEM_SIZE_BAR5_32 ) # # Event Types # # All event codes are unsigned long, so no _to_int() is necessary. # VI_EVENT_IO_COMPLETION = 0x3FFF2009 VI_EVENT_TRIG = 0xBFFF200A VI_EVENT_SERVICE_REQ = 0x3FFF200B VI_EVENT_CLEAR = 0x3FFF200D VI_EVENT_EXCEPTION = 0xBFFF200E VI_EVENT_GPIB_CIC = 0x3FFF2012 VI_EVENT_GPIB_TALK = 0x3FFF2013 VI_EVENT_GPIB_LISTEN = 0x3FFF2014 VI_EVENT_VXI_VME_SYSFAIL = 0x3FFF201D VI_EVENT_VXI_VME_SYSRESET = 0x3FFF201E VI_EVENT_VXI_SIGP = 0x3FFF2020 VI_EVENT_VXI_VME_INTR = 0xBFFF2021 VI_EVENT_PXI_INTR = 0x3FFF2022 VI_EVENT_TCPIP_CONNECT = 0x3FFF2036 VI_EVENT_USB_INTR = 0x3FFF2037 VI_ALL_ENABLED_EVENTS = 0x3FFF7FFF VI_ATTR_VXI_TRIG_DIR = _to_int(0x3FFF4044) VI_ATTR_VXI_TRIG_LINES_EN = _to_int(0x3FFF4043) # # Values and Ranges # VI_FIND_BUFLEN = 256 VI_NULL = 0 VI_TRUE = 1 VI_FALSE = 0 VI_INTF_GPIB = 1 VI_INTF_VXI = 2 VI_INTF_GPIB_VXI = 3 VI_INTF_ASRL = 4 VI_INTF_PXI = 5 VI_INTF_TCPIP = 6 VI_INTF_USB = 7 VI_INTF_RIO = 8 VI_INTF_FIREWIRE = 9 VI_PROT_NORMAL = 1 VI_PROT_FDC = 2 VI_PROT_HS488 = 3 VI_PROT_4882_STRS = 4 VI_PROT_USBTMC_VENDOR = 5 VI_FDC_NORMAL = 1 VI_FDC_STREAM = 2 VI_LOCAL_SPACE = 0 VI_A16_SPACE = 1 VI_A24_SPACE = 2 VI_A32_SPACE = 3 VI_A64_SPACE = 4 VI_OPAQUE_SPACE = 0xFFFF VI_UNKNOWN_LA = -1 VI_UNKNOWN_SLOT = -1 VI_UNKNOWN_LEVEL = -1 VI_QUEUE = 1 VI_HNDLR = 2 VI_SUSPEND_HNDLR = 4 VI_ALL_MECH = 0xFFFF VI_ANY_HNDLR = 0 VI_TRIG_ALL = -2 VI_TRIG_SW = -1 VI_TRIG_TTL0 = 0 VI_TRIG_TTL1 = 1 VI_TRIG_TTL2 = 2 VI_TRIG_TTL3 = 3 VI_TRIG_TTL4 = 4 VI_TRIG_TTL5 = 5 VI_TRIG_TTL6 = 6 VI_TRIG_TTL7 = 7 VI_TRIG_TTL8 = 32 VI_TRIG_TTL9 = 33 VI_TRIG_TTL10 = 34 VI_TRIG_TTL11 = 35 VI_TRIG_ECL0 = 8 VI_TRIG_ECL1 = 9 VI_TRIG_ECL2 = 10 VI_TRIG_ECL3 = 11 VI_TRIG_ECL4 = 12 VI_TRIG_ECL5 = 13 VI_TRIG_STAR_SLOT1 = 14 VI_TRIG_STAR_SLOT2 = 15 VI_TRIG_STAR_SLOT3 = 16 VI_TRIG_STAR_SLOT4 = 17 VI_TRIG_STAR_SLOT5 = 18 VI_TRIG_STAR_SLOT6 = 19 VI_TRIG_STAR_SLOT7 = 20 VI_TRIG_STAR_SLOT8 = 21 VI_TRIG_STAR_SLOT9 = 22 VI_TRIG_STAR_SLOT10 = 23 VI_TRIG_STAR_SLOT11 = 24 VI_TRIG_STAR_SLOT12 = 25 VI_TRIG_STAR_INSTR = 26 VI_TRIG_PANEL_IN = 27 VI_TRIG_PANEL_OUT = 28 VI_TRIG_STAR_VXI0 = 29 VI_TRIG_STAR_VXI1 = 30 VI_TRIG_STAR_VXI2 = 31 VI_TRIG_PROT_DEFAULT = 0 VI_TRIG_PROT_ON = 1 VI_TRIG_PROT_OFF = 2 VI_TRIG_PROT_SYNC = 5 VI_TRIG_PROT_RESERVE = 6 VI_TRIG_PROT_UNRESERVE = 7 VI_READ_BUF = 1 VI_WRITE_BUF = 2 VI_READ_BUF_DISCARD = 4 VI_WRITE_BUF_DISCARD = 8 VI_IO_IN_BUF = 16 VI_IO_OUT_BUF = 32 VI_IO_IN_BUF_DISCARD = 64 VI_IO_OUT_BUF_DISCARD = 128 VI_FLUSH_ON_ACCESS = 1 VI_FLUSH_WHEN_FULL = 2 VI_FLUSH_DISABLE = 3 VI_NMAPPED = 1 VI_USE_OPERS = 2 VI_DEREF_ADDR = 3 VI_TMO_IMMEDIATE = 0 # Attention! The following is *really* positive! (unsigned long) VI_TMO_INFINITE = 0xFFFFFFFF VI_NO_LOCK = 0 VI_EXCLUSIVE_LOCK = 1 VI_SHARED_LOCK = 2 VI_LOAD_CONFIG = 4 VI_NO_SEC_ADDR = 0xFFFF VI_ASRL_PAR_NONE = 0 VI_ASRL_PAR_ODD = 1 VI_ASRL_PAR_EVEN = 2 VI_ASRL_PAR_MARK = 3 VI_ASRL_PAR_SPACE = 4 VI_ASRL_STOP_ONE = 10 VI_ASRL_STOP_ONE5 = 15 VI_ASRL_STOP_TWO = 20 VI_ASRL_FLOW_NONE = 0 VI_ASRL_FLOW_XON_XOFF = 1 VI_ASRL_FLOW_RTS_CTS = 2 VI_ASRL_FLOW_DTR_DSR = 4 VI_ASRL_END_NONE = 0 VI_ASRL_END_LAST_BIT = 1 VI_ASRL_END_TERMCHAR = 2 VI_ASRL_END_BREAK = 3 # The following are National Instrument only VI_ASRL_WIRE_485_4 = 0 VI_ASRL_WIRE_485_2_DTR_ECHO = 1 VI_ASRL_WIRE_485_2_DTR_CTRL = 2 VI_ASRL_WIRE_485_2_AUTO = 3 VI_ASRL_WIRE_232_DTE = 128 VI_ASRL_WIRE_232_DCE = 129 VI_ASRL_WIRE_232_AUTO = 130 VI_STATE_ASSERTED = 1 VI_STATE_UNASSERTED = 0 VI_STATE_UNKNOWN = -1 VI_BIG_ENDIAN = 0 VI_LITTLE_ENDIAN = 1 VI_DATA_PRIV = 0 VI_DATA_NPRIV = 1 VI_PROG_PRIV = 2 VI_PROG_NPRIV = 3 VI_BLCK_PRIV = 4 VI_BLCK_NPRIV = 5 VI_D64_PRIV = 6 VI_D64_NPRIV = 7 VI_D64_2EVME = 8 VI_D64_SST160 = 9 VI_D64_SST267 = 10 VI_D64_SST320 = 11 VI_WIDTH_8 = 1 VI_WIDTH_16 = 2 VI_WIDTH_32 = 4 VI_WIDTH_64 = 8 VI_GPIB_REN_DEASSERT = 0 VI_GPIB_REN_ASSERT = 1 VI_GPIB_REN_DEASSERT_GTL = 2 VI_GPIB_REN_ASSERT_ADDRESS = 3 VI_GPIB_REN_ASSERT_LLO = 4 VI_GPIB_REN_ASSERT_ADDRESS_LLO = 5 VI_GPIB_REN_ADDRESS_GTL = 6 VI_GPIB_ATN_DEASSERT = 0 VI_GPIB_ATN_ASSERT = 1 VI_GPIB_ATN_DEASSERT_HANDSHAKE = 2 VI_GPIB_ATN_ASSERT_IMMEDIATE = 3 VI_GPIB_HS488_DISABLED = 0 VI_GPIB_HS488_NIMPL = -1 VI_GPIB_UNADDRESSED = 0 VI_GPIB_TALKER = 1 VI_GPIB_LISTENER = 2 VI_VXI_CMD16 = 0x0200 VI_VXI_CMD16_RESP16 = 0x0202 VI_VXI_RESP16 = 0x0002 VI_VXI_CMD32 = 0x0400 VI_VXI_CMD32_RESP16 = 0x0402 VI_VXI_CMD32_RESP32 = 0x0404 VI_VXI_RESP32 = 0x0004 VI_ASSERT_SIGNAL = -1 VI_ASSERT_USE_ASSIGNED = 0 VI_ASSERT_IRQ1 = 1 VI_ASSERT_IRQ2 = 2 VI_ASSERT_IRQ3 = 3 VI_ASSERT_IRQ4 = 4 VI_ASSERT_IRQ5 = 5 VI_ASSERT_IRQ6 = 6 VI_ASSERT_IRQ7 = 7 VI_UTIL_ASSERT_SYSRESET = 1 VI_UTIL_ASSERT_SYSFAIL = 2 VI_UTIL_DEASSERT_SYSFAIL = 3 VI_VXI_CLASS_MEMORY = 0 VI_VXI_CLASS_EXTENDED = 1 VI_VXI_CLASS_MESSAGE = 2 VI_VXI_CLASS_REGISTER = 3 VI_VXI_CLASS_OTHER = 4 VI_PXI_LBUS_UNKNOWN = -1 VI_PXI_LBUS_NONE = 0 VI_PXI_LBUS_STAR_TRIG_BUS_0 = 1000 VI_PXI_LBUS_STAR_TRIG_BUS_1 = 1001 VI_PXI_LBUS_STAR_TRIG_BUS_2 = 1002 VI_PXI_LBUS_STAR_TRIG_BUS_3 = 1003 VI_PXI_LBUS_STAR_TRIG_BUS_4 = 1004 VI_PXI_LBUS_STAR_TRIG_BUS_5 = 1005 VI_PXI_LBUS_STAR_TRIG_BUS_6 = 1006 VI_PXI_LBUS_STAR_TRIG_BUS_7 = 1007 VI_PXI_LBUS_STAR_TRIG_BUS_8 = 1008 VI_PXI_LBUS_STAR_TRIG_BUS_9 = 1009 VI_PXI_STAR_TRIG_CONTROLLER = 1413 VI_PXI_LBUS_SCXI = 2000 VI_PXI_ALLOC_SPACE = 9 VI_PXI_CFG_SPACE = 10 VI_PXI_BAR0_SPACE = 11 VI_PXI_BAR1_SPACE = 12 VI_PXI_BAR2_SPACE = 13 VI_PXI_BAR3_SPACE = 14 VI_PXI_BAR4_SPACE = 15 VI_PXI_BAR5_SPACE = 16 VI_PXI_ADDR_NONE = 0 VI_PXI_ADDR_MEM = 1 VI_PXI_ADDR_IO = 2 VI_PXI_ADDR_CFG = 3 VI_USB_PIPE_STATE_UNKNOWN = -1 VI_USB_PIPE_READY = 0 VI_USB_PIPE_STALLED = 1 # From VI_ATTR_USB_END_IN VI_USB_END_NONE = 0 VI_USB_END_SHORT = 4 VI_USB_END_SHORT_OR_COUNT = 5 # "Backwards compatibility" according to NI VI_NORMAL = VI_PROT_NORMAL VI_FDC = VI_PROT_FDC VI_HS488 = VI_PROT_HS488 VI_ASRL488 = VI_PROT_4882_STRS VI_ASRL_IN_BUF = VI_IO_IN_BUF VI_ASRL_OUT_BUF = VI_IO_OUT_BUF VI_ASRL_IN_BUF_DISCARD = VI_IO_IN_BUF_DISCARD VI_ASRL_OUT_BUF_DISCARD = VI_IO_OUT_BUF_DISCARD # fmt: on # ====================================================================================== # --- Enumeration for easier handling of the constants --------------------------------- # ====================================================================================== @enum.unique class VisaBoolean(enum.IntEnum): """Visa boolean values.""" true = VI_TRUE false = VI_FALSE # Constants useful for all kind of resources. @enum.unique class Timeouts(enum.IntEnum): """Special timeout values.""" #: Minimal timeout value immediate = VI_TMO_IMMEDIATE #: Infinite timeout infinite = VI_TMO_INFINITE @enum.unique class Lock(enum.IntEnum): """Kind of lock to use when locking a resource.""" #: Obtains a exclusive lock on the VISA resource. exclusive = VI_EXCLUSIVE_LOCK #: Obtains a lock on the VISA resouce which may be shared #: between multiple VISA sessions. shared = VI_SHARED_LOCK @enum.unique class AccessModes(enum.IntEnum): """Whether and how to lock a resource when opening a connection.""" #: Does not obtain any lock on the VISA resource. no_lock = VI_NO_LOCK #: Obtains a exclusive lock on the VISA resource. exclusive_lock = VI_EXCLUSIVE_LOCK #: Obtains a lock on the VISA resouce which may be shared #: between multiple VISA sessions. shared_lock = VI_SHARED_LOCK @enum.unique class InterfaceType(enum.IntEnum): """The hardware interface.""" # Used for unknown interface type strings. unknown = -1 #: GPIB Interface. gpib = VI_INTF_GPIB #: VXI (VME eXtensions for Instrumentation), VME, MXI (Multisystem eXtension Interface). vxi = VI_INTF_VXI #: GPIB VXI (VME eXtensions for Instrumentation). gpib_vxi = VI_INTF_GPIB_VXI #: Serial devices connected to either an RS-232 or RS-485 controller. asrl = VI_INTF_ASRL #: PXI device. pxi = VI_INTF_PXI #: TCPIP device. tcpip = VI_INTF_TCPIP #: Universal Serial Bus (USB) hardware bus. usb = VI_INTF_USB #: Rio device. rio = VI_INTF_RIO #: Firewire device. firewire = VI_INTF_FIREWIRE #: Rohde and Schwarz Device via Passport rsnrp = 33024 @enum.unique class LineState(enum.IntEnum): """State of a hardware line or signal. The line for which the state can be queried are: - ASRC resource: BREAK, CTS, DCD, DSR, DTR, RI, RTS signals - GPIB resources: ATN, NDAC, REN, SRQ lines - VXI BACKPLANE: VXI/VME SYSFAIL backplane line Search for LineState in attributes.py for more details. """ #: The line/signal is currently asserted asserted = VI_STATE_ASSERTED #: The line/signal is currently deasserted unasserted = VI_STATE_UNASSERTED #: The state of the line/signal is unknown unknown = VI_STATE_UNKNOWN @enum.unique class IOProtocol(enum.IntEnum): """IO protocol used for communication. See attributes.AttrVI_ATTR_IO_PROT for more details. """ normal = VI_PROT_NORMAL #: Fast data channel (FDC) protocol for VXI fdc = VI_PROT_FDC #: High speed 488 transfer for GPIB hs488 = VI_PROT_HS488 #: 488 style transfer for serial protocol4882_strs = VI_PROT_4882_STRS #: Test measurement class vendor specific for USB usbtmc_vendor = VI_PROT_USBTMC_VENDOR @enum.unique class EventMechanism(enum.IntEnum): """The available event mechanisms for event handling.""" #: Queue events that can then be queried using wait_on_event queue = VI_QUEUE #: Use a specified callback handler to deal with events handler = VI_HNDLR #: Queue events to be passed to the handler when the system is switch to the #: handler mechanism. suspend_handler = VI_SUSPEND_HNDLR #: Use to disable or discard events no matter the handling mechanism all = VI_ALL_MECH # Message based resources relevant constants @enum.unique class EventType(enum.IntEnum): """The available event types for event handling.""" #: Notification that an asynchronous operation has completed. io_completion = VI_EVENT_IO_COMPLETION #: Notification that a trigger interrupt was received from the device. #: For VISA, the only triggers that can be sensed are VXI hardware triggers #: on the assertion edge (SYNC and ON trigger protocols only). trig = VI_EVENT_TRIG #: Notification that a service request was received from the device. service_request = VI_EVENT_SERVICE_REQ #: Notification that the local controller has been sent a device clear message. clear = VI_EVENT_CLEAR #: Notification that an error condition has occurred during an operation #: invocation. exception = VI_EVENT_EXCEPTION #: Notification that the GPIB controller has gained or lost CIC (controller #: in charge) status. gpib_controller_in_charge = VI_EVENT_GPIB_CIC #: Notification that the GPIB controller has been addressed to talk. gpib_talk = VI_EVENT_GPIB_TALK #: Notification that the GPIB controller has been addressed to listen. gpib_listen = VI_EVENT_GPIB_LISTEN #: Notification that the VXI/VME SYSFAIL* line has been asserted. vxi_vme_sysfail = VI_EVENT_VXI_VME_SYSFAIL #: Notification that the VXI/VME SYSRESET* line has been asserted. vxi_vme_sysreset = VI_EVENT_VXI_VME_SYSRESET #: Notification that a VXIbus signal or VXIbus interrupt was received from #: the device. vxi_signal_interrupt = VI_EVENT_VXI_SIGP #: Notification that a VXIbus interrupt was received from the device. vxi_vme_interrupt = VI_EVENT_VXI_VME_INTR #: Notification that a PCI Interrupt was received from the device. pxi_interrupt = VI_EVENT_PXI_INTR #: Notification that a TCP/IP connection has been made. tcpip_connect = VI_EVENT_TCPIP_CONNECT #: Notification that a vendor-specific USB interrupt was received from the device. usb_interrupt = VI_EVENT_USB_INTR #: Value equivalent to all events. Use to switch handling mechanism for all #: events in one call or disabling all events. all_enabled = VI_ALL_ENABLED_EVENTS @enum.unique class BufferType(enum.IntFlag): """Buffer potentially available on a message based resource. Used with the set_buffer function to alter the size of a buffer. """ #: Formatted read buffer read = VI_READ_BUF #: Formatted write buffer write = VI_WRITE_BUF #: I/O communication receive buffer. io_in = VI_IO_IN_BUF #: I/O communication transmit buffer. io_out = VI_IO_OUT_BUF @enum.unique class BufferOperation(enum.IntFlag): """Possible action of the buffer when performing a flush.""" #: Discard the read buffer contents and if data was present in the read buffer #: and no END-indicator was present, read from the device until encountering #: an END indicator (which causes the loss of data). discard_read_buffer = VI_READ_BUF #: Discard the read buffer contents (does not perform any I/O to the device). discard_read_buffer_no_io = VI_READ_BUF_DISCARD #: Flush the write buffer by writing all buffered data to the device. flush_write_buffer = VI_WRITE_BUF #: Discard the write buffer contents (does not perform any I/O to the device). discard_write_buffer = VI_WRITE_BUF_DISCARD #: Discard the receive buffer contents (does not perform any I/O to the device). discard_receive_buffer = VI_IO_IN_BUF_DISCARD #: Discards the receive buffer contents (same as VI_IO_IN_BUF_DISCARD) discard_receive_buffer2 = VI_IO_IN_BUF #: Flush the transmit buffer by writing all buffered data to the device. flush_transmit_buffer = VI_IO_OUT_BUF #: Discard the transmit buffer contents (does not perform any I/O to the device). discard_transmit_buffer = VI_IO_OUT_BUF_DISCARD # Constants related to serial resources @enum.unique class StopBits(enum.IntEnum): """The number of stop bits that indicate the end of a frame on a serial resource. Used only for ASRL resources. """ one = VI_ASRL_STOP_ONE one_and_a_half = VI_ASRL_STOP_ONE5 two = VI_ASRL_STOP_TWO @enum.unique class Parity(enum.IntEnum): """Parity type to use with every frame transmitted and received on a serial session. Used only for ASRL resources. """ none = VI_ASRL_PAR_NONE odd = VI_ASRL_PAR_ODD even = VI_ASRL_PAR_EVEN mark = VI_ASRL_PAR_MARK space = VI_ASRL_PAR_SPACE @enum.unique class SerialTermination(enum.IntEnum): """The available methods for terminating a serial transfer.""" #: The transfer terminates when all requested data is transferred #: or when an error occurs. none = VI_ASRL_END_NONE #: The transfer occurs with the last bit not set until the last #: character is sent. last_bit = VI_ASRL_END_LAST_BIT #: The transfer terminate by searching for "/" #: appending the termination character. termination_char = VI_ASRL_END_TERMCHAR #: The write transmits a break after all the characters for the #: write are sent. termination_break = VI_ASRL_END_BREAK @enum.unique class WireMode(enum.IntEnum): """Valid modes for National Instruments hardware supporting it.""" #: 4-wire mode. rs485_4 = VI_ASRL_WIRE_485_4 #: 2-wire DTR mode controlled with echo. rs485_2_dtr_echo = VI_ASRL_WIRE_485_2_DTR_ECHO #: 2-wire DTR mode controlled without echo rs485_2_dtr_ctrl = VI_ASRL_WIRE_485_2_DTR_CTRL #: 2-wire auto mode controlled with TXRDY rs485_2_auto = VI_ASRL_WIRE_485_2_AUTO #: Use DTE mode rs232_dte = VI_ASRL_WIRE_232_DTE #: Use DCE mode rs232_dce = VI_ASRL_WIRE_232_DCE #: Auto detect the mode to use rs232_auto = VI_ASRL_WIRE_232_AUTO #: Unknown mode unknown = VI_STATE_UNKNOWN @enum.unique class ControlFlow(enum.IntEnum): """Control flow for a serial resource.""" none = VI_ASRL_FLOW_NONE xon_xoff = VI_ASRL_FLOW_XON_XOFF rts_cts = VI_ASRL_FLOW_RTS_CTS dtr_dsr = VI_ASRL_FLOW_DTR_DSR # USB specific constants @enum.unique class USBEndInput(enum.IntEnum): """Method used to terminate input on USB RAW.""" none = VI_USB_END_NONE short = VI_USB_END_SHORT short_or_count = VI_USB_END_SHORT_OR_COUNT # GPIB specific value @enum.unique class AddressState(enum.IntEnum): """State of a GPIB resource. Corresponds to the Attribute.GPIB_address_state attribute """ #: The resource is unadressed unaddressed = VI_GPIB_UNADDRESSED #: The resource is addressed to talk talker = VI_GPIB_TALKER #: The resource is addressed to listen listenr = VI_GPIB_LISTENER @enum.unique class ATNLineOperation(enum.IntEnum): """Operation that can be performed on the GPIB ATN line. These operations are available only to GPIB INTFC resources """ #: Assert ATN line synchronously (in 488 terminology). If a data handshake #: is in progress, ATN will not be asserted until the handshake is complete. asrt = VI_GPIB_ATN_ASSERT #: Assert ATN line asynchronously (in 488 terminology). This should generally #: be used only under error conditions. asrt_immediate = VI_GPIB_ATN_ASSERT_IMMEDIATE #: Deassert the ATN line deassert = VI_GPIB_ATN_DEASSERT #: Deassert ATN line, and enter shadow handshake mode. The local board will #: participate in data handshakes as an Acceptor without actually reading the data. deassert_handshake = VI_GPIB_ATN_DEASSERT_HANDSHAKE @enum.unique class RENLineOperation(enum.IntEnum): """Operation that can be performed on the REN line. Some of these operation are available to GPIB INSTR, GPIB INTFC, USB INSTR, TCPIP INSTR, please see the VISA reference for more details. """ #: Send the Go To Local command (GTL) to this device. address_gtl = VI_GPIB_REN_ADDRESS_GTL #: Assert REN line. asrt = VI_GPIB_REN_ASSERT #: Assert REN line and address this device. asrt_address = VI_GPIB_REN_ASSERT_ADDRESS #: Address this device and send it LLO, putting it in RWLS asrt_address_llo = VI_GPIB_REN_ASSERT_ADDRESS_LLO #: Send LLO to any devices that are addressed to listen. asrt_llo = VI_GPIB_REN_ASSERT_LLO #: Deassert REN line. deassert = VI_GPIB_REN_DEASSERT #: Send the Go To Local command (GTL) to this device and deassert REN line. deassert_gtl = VI_GPIB_REN_DEASSERT_GTL @enum.unique class AddressSpace(enum.IntEnum): """Address space for register based resources.""" #: A16 address space of VXI/MXI bus. a16 = VI_A16_SPACE #: A24 address space of VXI/MXI bus. a24 = VI_A24_SPACE #: A32 address space of VXI/MXI bus. a32 = VI_A32_SPACE #: A64 address space of VXI/MXI bus. a64 = VI_A64_SPACE #: PCI configuration space. pxi_config = VI_PXI_CFG_SPACE #: Specified PCI memory or I/O space pxi_bar0 = VI_PXI_BAR0_SPACE pxi_bar1 = VI_PXI_BAR1_SPACE pxi_bar2 = VI_PXI_BAR2_SPACE pxi_bar3 = VI_PXI_BAR3_SPACE pxi_bar4 = VI_PXI_BAR4_SPACE pxi_bar5 = VI_PXI_BAR5_SPACE #: Physical locally allocated memory. pxi_allocated = VI_PXI_ALLOC_SPACE @enum.unique class AddressModifiers(enum.IntEnum): """Address modifier to be used in high-level register operations.""" data_private = VI_DATA_PRIV data_non_private = VI_DATA_NPRIV program_private = VI_PROG_PRIV program_non_private = VI_PROG_NPRIV block_private = VI_BLCK_PRIV block_non_private = VI_BLCK_NPRIV d64_private = VI_D64_PRIV d64_non_private = VI_D64_NPRIV d64_2vme = VI_D64_2EVME d64_sst160 = VI_D64_SST160 d64_sst267 = VI_D64_SST267 d64_sst320 = VI_D64_SST320 @enum.unique class AssertSignalInterrupt(enum.IntEnum): """Line on which to perform an assertion or interrupt. Used only for VXI backplane and servant resources. """ #: Use a VXI signal signal = VI_ASSERT_SIGNAL #: Use the mechanism specified in the response of Asynchronous Mode Control #: command. (VXI SERVANT only) use_assigned = VI_ASSERT_USE_ASSIGNED #: Send the interrupt via the specified VXI/VME IRQ line irq1 = VI_ASSERT_IRQ1 irq2 = VI_ASSERT_IRQ2 irq3 = VI_ASSERT_IRQ3 irq4 = VI_ASSERT_IRQ4 irq5 = VI_ASSERT_IRQ5 irq6 = VI_ASSERT_IRQ6 irq7 = VI_ASSERT_IRQ7 @enum.unique class UtilityBusSignal(enum.IntEnum): """Operation on the utility line of a VXI backplane or servant.""" #: Assert the SYSRESET ie perform a HARD RESET on the whole VXI bus. sysrest = VI_UTIL_ASSERT_SYSRESET #: Assert the SYSFAIL line. sysfail_assert = VI_UTIL_ASSERT_SYSFAIL #: Deassert the SYSFAIL line. sysfail_deassert = VI_UTIL_DEASSERT_SYSFAIL @enum.unique class VXICommands(enum.IntEnum): """VXI commands that can be sent using the vxi_command_query.""" #: Send a command fitting in a 16-bit integer command_16 = VI_VXI_CMD16 #: Read a response fitting in a 16-bit integer response16 = VI_VXI_RESP16 #: Send a command and read a response both fitting in a 16-bit integer command_response_16 = VI_VXI_CMD16_RESP16 #: Send a command fitting in a 32-bit integer command_32 = VI_VXI_CMD32 #: Read a response fitting in a 32-bit integer response32 = VI_VXI_RESP32 #: Send a command and read a response both fitting in a 32-bit integer command_response_32 = VI_VXI_CMD32_RESP32 #: Send a command (32-bit integer) and read a response (16-bit integer) command_32_response_16 = VI_VXI_CMD32_RESP16 @enum.unique class PXIMemory(enum.IntEnum): """Memory type used in a PXI BAR.""" none = VI_PXI_ADDR_NONE memory = VI_PXI_ADDR_MEM io = VI_PXI_ADDR_IO cfg = VI_PXI_ADDR_CFG @enum.unique class VXIClass(enum.IntEnum): """VXI-defined device class.""" memory = VI_VXI_CLASS_MEMORY extended = VI_VXI_CLASS_EXTENDED message = VI_VXI_CLASS_MESSAGE register = VI_VXI_CLASS_REGISTER other = VI_VXI_CLASS_OTHER @enum.unique class TriggerProtocol(enum.IntEnum): """Trigger protocol used when assering a resource trigger.""" # FIXME The VISA standard is not very detailed on those #: Default protocol. #: This is the only valid protocol for software trigger on ASRL, GPIB, USB #: and VXI resources default = VI_TRIG_PROT_DEFAULT #: on = VI_TRIG_PROT_ON #: off = VI_TRIG_PROT_OFF #: For VXI devices equivalent to default sync = VI_TRIG_PROT_SYNC #: On PXI resources used to reserve a line for triggering reserve = VI_TRIG_PROT_RESERVE #: On PXI resources used to unreserve a line for triggering unreserve = VI_TRIG_PROT_UNRESERVE @enum.unique class InputTriggerLine(enum.IntEnum): """Trigger lines which can be mapped to another line. VXI, PXI devices. """ #: TTL trigger lines ttl0 = VI_TRIG_TTL0 ttl1 = VI_TRIG_TTL1 ttl2 = VI_TRIG_TTL2 ttl3 = VI_TRIG_TTL3 ttl4 = VI_TRIG_TTL4 ttl5 = VI_TRIG_TTL5 ttl6 = VI_TRIG_TTL6 ttl7 = VI_TRIG_TTL7 # PXI specific TTL trigger lines ttl8 = VI_TRIG_TTL8 ttl9 = VI_TRIG_TTL9 ttl10 = VI_TRIG_TTL10 ttl11 = VI_TRIG_TTL11 #: ECL trigger lines ecl0 = VI_TRIG_ECL0 ecl1 = VI_TRIG_ECL1 ecl2 = VI_TRIG_ECL2 ecl3 = VI_TRIG_ECL3 ecl4 = VI_TRIG_ECL4 ecl5 = VI_TRIG_ECL5 #: Panel IN trigger line panel = VI_TRIG_PANEL_IN #: VXI STAR trigger input lines slot1 = VI_TRIG_STAR_SLOT1 slot2 = VI_TRIG_STAR_SLOT2 slot3 = VI_TRIG_STAR_SLOT3 slot4 = VI_TRIG_STAR_SLOT4 slot5 = VI_TRIG_STAR_SLOT5 slot6 = VI_TRIG_STAR_SLOT6 slot7 = VI_TRIG_STAR_SLOT7 slot8 = VI_TRIG_STAR_SLOT8 slot9 = VI_TRIG_STAR_SLOT9 slot10 = VI_TRIG_STAR_SLOT10 slot11 = VI_TRIG_STAR_SLOT11 slot12 = VI_TRIG_STAR_SLOT12 @enum.unique class OutputTriggerLine(enum.IntEnum): """Trigger lines to which another line can be mapped to. VXI, PXI devices. """ #: TTL trigger lines ttl0 = VI_TRIG_TTL0 ttl1 = VI_TRIG_TTL1 ttl2 = VI_TRIG_TTL2 ttl3 = VI_TRIG_TTL3 ttl4 = VI_TRIG_TTL4 ttl5 = VI_TRIG_TTL5 ttl6 = VI_TRIG_TTL6 ttl7 = VI_TRIG_TTL7 # PXI specific TTL trigger lines ttl8 = VI_TRIG_TTL8 ttl9 = VI_TRIG_TTL9 ttl10 = VI_TRIG_TTL10 ttl11 = VI_TRIG_TTL11 #: VXI ECL trigger lines ecl0 = VI_TRIG_ECL0 ecl1 = VI_TRIG_ECL1 ecl2 = VI_TRIG_ECL2 ecl3 = VI_TRIG_ECL3 ecl4 = VI_TRIG_ECL4 ecl5 = VI_TRIG_ECL5 #: VXI STAR trigger out lines vxi0 = VI_TRIG_STAR_VXI0 vxi1 = VI_TRIG_STAR_VXI1 vxi2 = VI_TRIG_STAR_VXI2 #: Panel OUT trigger line panel = VI_TRIG_PANEL_OUT #: All trigger lines (used only when unmapping lines) all = VI_TRIG_ALL @enum.unique class TriggerID(enum.IntEnum): """Identifier of the currently active trigerring mechanism on a resource.""" #: Trigger using a serial word serial_word = VI_TRIG_SW #: TTL trigger lines ttl0 = VI_TRIG_TTL0 ttl1 = VI_TRIG_TTL1 ttl2 = VI_TRIG_TTL2 ttl3 = VI_TRIG_TTL3 ttl4 = VI_TRIG_TTL4 ttl5 = VI_TRIG_TTL5 ttl6 = VI_TRIG_TTL6 ttl7 = VI_TRIG_TTL7 # PXI specific TTL trigger lines ttl8 = VI_TRIG_TTL8 ttl9 = VI_TRIG_TTL9 ttl10 = VI_TRIG_TTL10 ttl11 = VI_TRIG_TTL11 #: VXI ECL trigger lines ecl0 = VI_TRIG_ECL0 ecl1 = VI_TRIG_ECL1 ecl2 = VI_TRIG_ECL2 ecl3 = VI_TRIG_ECL3 ecl4 = VI_TRIG_ECL4 ecl5 = VI_TRIG_ECL5 #: VXI STAR trigger out lines vxi0 = VI_TRIG_STAR_VXI0 vxi1 = VI_TRIG_STAR_VXI1 vxi2 = VI_TRIG_STAR_VXI2 #: FIXME No definition in the VISA standards instr = VI_TRIG_STAR_INSTR @enum.unique class TriggerEventID(enum.IntEnum): """Identifier of the triggering mechanism on which a trigger event was received.""" #: TTL trigger lines ttl0 = VI_TRIG_TTL0 ttl1 = VI_TRIG_TTL1 ttl2 = VI_TRIG_TTL2 ttl3 = VI_TRIG_TTL3 ttl4 = VI_TRIG_TTL4 ttl5 = VI_TRIG_TTL5 ttl6 = VI_TRIG_TTL6 ttl7 = VI_TRIG_TTL7 # PXI specific TTL trigger lines ttl8 = VI_TRIG_TTL8 ttl9 = VI_TRIG_TTL9 ttl10 = VI_TRIG_TTL10 ttl11 = VI_TRIG_TTL11 #: VXI ECL trigger lines ecl0 = VI_TRIG_ECL0 ecl1 = VI_TRIG_ECL1 ecl2 = VI_TRIG_ECL2 ecl3 = VI_TRIG_ECL3 ecl4 = VI_TRIG_ECL4 ecl5 = VI_TRIG_ECL5 #: FIXME No definition in the VISA standards instr = VI_TRIG_STAR_INSTR @enum.unique class ByteOrder(enum.IntEnum): """Byte order in register data transfer.""" big_endian = VI_BIG_ENDIAN little_endian = VI_LITTLE_ENDIAN @enum.unique class DataWidth(enum.IntEnum): """Word width used when transferring data to/from register based resources.""" #: Transfer data using 1 byte word bit_8 = VI_WIDTH_8 #: Transfer data using 2 byte word bit_16 = VI_WIDTH_16 #: Transfer data using 4 byte word bit_32 = VI_WIDTH_32 #: Transfer data using 8 byte word bit_64 = VI_WIDTH_64 @classmethod def from_literal(cls, value: Literal[8, 16, 32, 64]) -> "DataWidth": """Convert a literal width in the proper enum value.""" if value not in (8, 16, 32, 64): raise ValueError( f"Invalid datawidth {value} specified. Valid values are (8, 16, 32, 64" ) return cls(value // 8) # Status code @enum.unique class StatusCode(enum.IntEnum): """Status codes that VISA driver-level operations can return.""" #: The operation was aborted. error_abort = VI_ERROR_ABORT #: Insufficient system resources to perform necessary memory allocation. error_allocation = VI_ERROR_ALLOC #: The specified attribute is read-only. error_attribute_read_only = VI_ERROR_ATTR_READONLY #: Bus error occurred during transfer. error_bus_error = VI_ERROR_BERR #: Unable to deallocate the previously allocated data structures corresponding #: to this session or object reference. error_closing_failed = VI_ERROR_CLOSING_FAILED #: The connection for the specified session has been lost. error_connection_lost = VI_ERROR_CONN_LOST #: An error occurred while trying to open the specified file. #: Possible causes include an invalid path or lack of access rights. error_file_access = VI_ERROR_FILE_ACCESS #: An error occurred while performing I/O on the specified file. error_file_i_o = VI_ERROR_FILE_IO #: A handler is not currently installed for the specified event. error_handler_not_installed = VI_ERROR_HNDLR_NINSTALLED #: Unable to queue the asynchronous operation because there is already #: an operation in progress. error_in_progress = VI_ERROR_IN_PROGRESS #: Device reported an input protocol error during transfer. error_input_protocol_violation = VI_ERROR_INP_PROT_VIOL #: The interface type is valid but the specified interface number is not configured. error_interface_number_not_configured = VI_ERROR_INTF_NUM_NCONFIG #: An interrupt is still pending from a previous call. error_interrupt_pending = VI_ERROR_INTR_PENDING #: The access key to the resource associated with this session is invalid. error_invalid_access_key = VI_ERROR_INV_ACCESS_KEY #: Invalid access mode. error_invalid_access_mode = VI_ERROR_INV_ACC_MODE #: Invalid address space specified. error_invalid_address_space = VI_ERROR_INV_SPACE #: Specified event context is invalid. error_invalid_context = VI_ERROR_INV_CONTEXT #: Specified degree is invalid. error_invalid_degree = VI_ERROR_INV_DEGREE #: Specified event type is not supported by the resource. error_invalid_event = VI_ERROR_INV_EVENT #: Invalid expression specified for search. error_invalid_expression = VI_ERROR_INV_EXPR #: A format specifier in the format string is invalid. error_invalid_format = VI_ERROR_INV_FMT #: The specified handler reference is invalid. error_invalid_handler_reference = VI_ERROR_INV_HNDLR_REF #: Specified job identifier is invalid. error_invalid_job_i_d = VI_ERROR_INV_JOB_ID #: Invalid length specified. error_invalid_length = VI_ERROR_INV_LENGTH #: The value specified by the line parameter is invalid. error_invalid_line = VI_ERROR_INV_LINE #: The specified type of lock is not supported by this resource. error_invalid_lock_type = VI_ERROR_INV_LOCK_TYPE #: Invalid buffer mask specified. error_invalid_mask = VI_ERROR_INV_MASK #: Invalid mechanism specified. error_invalid_mechanism = VI_ERROR_INV_MECH #: The specified mode is invalid. error_invalid_mode = VI_ERROR_INV_MODE #: The specified session or object reference is invalid. error_invalid_object = VI_ERROR_INV_OBJECT #: Invalid offset specified. error_invalid_offset = VI_ERROR_INV_OFFSET #: The value of an unknown parameter is invalid. error_invalid_parameter = VI_ERROR_INV_PARAMETER #: The protocol specified is invalid. error_invalid_protocol = VI_ERROR_INV_PROT #: Invalid resource reference specified. Parsing error. error_invalid_resource_name = VI_ERROR_INV_RSRC_NAME #: Unable to start operation because setup is invalid due to inconsistent #: state of properties. error_invalid_setup = VI_ERROR_INV_SETUP #: Invalid size of window specified. error_invalid_size = VI_ERROR_INV_SIZE #: Invalid source or destination width specified. error_invalid_width = VI_ERROR_INV_WIDTH #: Could not perform operation because of I/O error. error_io = VI_ERROR_IO #: A code library required by VISA could not be located or loaded. error_library_not_found = VI_ERROR_LIBRARY_NFOUND #: The specified trigger line is currently in use. error_line_in_use = VI_ERROR_LINE_IN_USE #: The remote machine does not exist or is not accepting any connections. error_machine_not_available = VI_ERROR_MACHINE_NAVAIL #: The device does not export any memory. error_memory_not_shared = VI_ERROR_MEM_NSHARED #: No listeners condition is detected (both NRFD and NDAC are deasserted). error_no_listeners = VI_ERROR_NLISTENERS #: The specified operation is unimplemented. error_nonimplemented_operation = VI_ERROR_NIMPL_OPER #: The specified attribute is not defined or supported by the referenced #: session, event, or find list. error_nonsupported_attribute = VI_ERROR_NSUP_ATTR #: The specified state of the attribute is not valid or is not supported as #: defined by the session, event, or find list. error_nonsupported_attribute_state = VI_ERROR_NSUP_ATTR_STATE #: A format specifier in the format string is not supported. error_nonsupported_format = VI_ERROR_NSUP_FMT #: The interface cannot generate an interrupt on the requested level or with #: the requested statusID value. error_nonsupported_interrupt = VI_ERROR_NSUP_INTR #: The specified trigger source line (trigSrc) or destination line (trigDest) #: is not supported by this VISA implementation, or the combination of lines #: is not a valid mapping. error_nonsupported_line = VI_ERROR_NSUP_LINE #: The specified mechanism is not supported for the specified event type. error_nonsupported_mechanism = VI_ERROR_NSUP_MECH #: The specified mode is not supported by this VISA implementation. error_nonsupported_mode = VI_ERROR_NSUP_MODE #: Specified offset is not accessible from this hardware. error_nonsupported_offset = VI_ERROR_NSUP_OFFSET #: The specified offset is not properly aligned for the access width of #: the operation. error_nonsupported_offset_alignment = VI_ERROR_NSUP_ALIGN_OFFSET #: The session or object reference does not support this operation. error_nonsupported_operation = VI_ERROR_NSUP_OPER #: Cannot support source and destination widths that are different. error_nonsupported_varying_widths = VI_ERROR_NSUP_VAR_WIDTH #: Specified width is not supported by this hardware. error_nonsupported_width = VI_ERROR_NSUP_WIDTH #: Access to the remote machine is denied. error_no_permission = VI_ERROR_NPERMISSION #: The interface associated with this session is not currently the #: Controller-in-Charge. error_not_cic = VI_ERROR_NCIC #: The session must be enabled for events of the specified type in order to #: receive them. error_not_enabled = VI_ERROR_NENABLED #: The interface associated with this session is not the system controller. error_not_system_controller = VI_ERROR_NSYS_CNTLR #: Device reported an output protocol error during transfer. error_output_protocol_violation = VI_ERROR_OUTP_PROT_VIOL #: Unable to queue asynchronous operation. error_queue_error = VI_ERROR_QUEUE_ERROR #: The event queue for the specified type has overflowed, usually due to #: not closing previous events. error_queue_overflow = VI_ERROR_QUEUE_OVERFLOW #: Violation of raw read protocol occurred during transfer. error_raw_read_protocol_violation = VI_ERROR_RAW_RD_PROT_VIOL #: Violation of raw write protocol occurred during transfer. error_raw_write_protocol_violation = VI_ERROR_RAW_WR_PROT_VIOL #: The resource is valid, but VISA cannot currently access it. error_resource_busy = VI_ERROR_RSRC_BUSY #: Specified type of lock cannot be obtained or specified operation cannot #: be performed because the resource is locked. error_resource_locked = VI_ERROR_RSRC_LOCKED #: Insufficient location information, or the device or resource is not #: present in the system. error_resource_not_found = VI_ERROR_RSRC_NFOUND #: A previous response is still pending, causing a multiple query error. error_response_pending = VI_ERROR_RESP_PENDING #: A framing error occurred during transfer. error_serial_framing = VI_ERROR_ASRL_FRAMING #: An overrun error occurred during transfer. A character was not read from #: the hardware before the next character arrived. error_serial_overrun = VI_ERROR_ASRL_OVERRUN #: A parity error occurred during transfer. error_serial_parity = VI_ERROR_ASRL_PARITY #: The current session did not have any lock on the resource. error_session_not_locked = VI_ERROR_SESN_NLOCKED #: Service request has not been received for the session. error_srq_not_occurred = VI_ERROR_SRQ_NOCCURRED #: Unknown system error. error_system_error = VI_ERROR_SYSTEM_ERROR #: Timeout expired before operation completed. error_timeout = VI_ERROR_TMO #: The path from the trigger source line (trigSrc) to the destination line #: (trigDest) is not currently mapped. error_trigger_not_mapped = VI_ERROR_TRIG_NMAPPED #: A specified user buffer is not valid or cannot be accessed for the #: required size. error_user_buffer = VI_ERROR_USER_BUF #: The specified session currently contains a mapped window. error_window_already_mapped = VI_ERROR_WINDOW_MAPPED #: The specified session is currently unmapped. error_window_not_mapped = VI_ERROR_WINDOW_NMAPPED #: Operation completed successfully. success = VI_SUCCESS #: Session opened successfully, but the device at the specified address is #: not responding. success_device_not_present = VI_SUCCESS_DEV_NPRESENT #: Specified event is already disabled for at least one of the specified mechanisms. success_event_already_disabled = VI_SUCCESS_EVENT_DIS #: Specified event is already enabled for at least one of the specified mechanisms. success_event_already_enabled = VI_SUCCESS_EVENT_EN #: The number of bytes read is equal to the input count. success_max_count_read = VI_SUCCESS_MAX_CNT #: Operation completed successfully, and this session has nested exclusive locks. success_nested_exclusive = VI_SUCCESS_NESTED_EXCLUSIVE #: Operation completed successfully, and this session has nested shared locks. success_nested_shared = VI_SUCCESS_NESTED_SHARED #: Event handled successfully. Do not invoke any other handlers on this session #: for this event. success_no_more_handler_calls_in_chain = VI_SUCCESS_NCHAIN #: Operation completed successfully, but the queue was already empty. success_queue_already_empty = VI_SUCCESS_QUEUE_EMPTY #: Wait terminated successfully on receipt of an event notification. There #: is still at least one more event occurrence of the requested type(s) #: available for this session. success_queue_not_empty = VI_SUCCESS_QUEUE_NEMPTY #: Asynchronous operation request was performed synchronously. success_synchronous = VI_SUCCESS_SYNC #: The specified termination character was read. success_termination_character_read = VI_SUCCESS_TERM_CHAR #: The path from the trigger source line (trigSrc) to the destination line #: (trigDest) is already mapped. success_trigger_already_mapped = VI_SUCCESS_TRIG_MAPPED #: The specified configuration either does not exist or could not be loaded. #: The VISA-specified defaults are used. warning_configuration_not_loaded = VI_WARN_CONFIG_NLOADED #: The operation succeeded, but a lower level driver did not implement the #: extended functionality. warning_ext_function_not_implemented = VI_WARN_EXT_FUNC_NIMPL #: Although the specified state of the attribute is valid, it is not supported #: by this resource implementation. warning_nonsupported_attribute_state = VI_WARN_NSUP_ATTR_STATE #: The specified buffer is not supported. warning_nonsupported_buffer = VI_WARN_NSUP_BUF #: The specified object reference is uninitialized. warning_null_object = VI_WARN_NULL_OBJECT #: VISA received more event information of the specified type than the #: configured queue size could hold. warning_queue_overflow = VI_WARN_QUEUE_OVERFLOW #: The status code passed to the operation could not be interpreted. warning_unknown_status = VI_WARN_UNKNOWN_STATUS # --- Attributes ----------------------------------------------------------------------- @enum.unique class EventAttribute(enum.IntEnum): """The possible attributes of VISA events.""" event_type = VI_ATTR_EVENT_TYPE status = VI_ATTR_STATUS operation_name = VI_ATTR_OPER_NAME job_id = VI_ATTR_JOB_ID return_count = VI_ATTR_RET_COUNT buffer = VI_ATTR_BUFFER received_trigger_id = VI_ATTR_RECV_TRIG_ID gpib_received_cic_state = VI_ATTR_GPIB_RECV_CIC_STATE received_tcpip_connect = VI_ATTR_RECV_TCPIP_ADDR usb_received_interrupt_size = VI_ATTR_USB_RECV_INTR_SIZE usb_received_interrupt_data = VI_ATTR_USB_RECV_INTR_DATA signal_register_status_id = VI_ATTR_SIGP_STATUS_ID interrupt_status_id = VI_ATTR_INTR_STATUS_ID received_interrupt_level = VI_ATTR_RECV_INTR_LEVEL pxi_received_interrupt_sequence = VI_ATTR_PXI_RECV_INTR_SEQ pxi_received_interrupt_data = VI_ATTR_PXI_RECV_INTR_DATA @enum.unique class ResourceAttribute(enum.IntEnum): """The possible attributes of VISA resources.""" # All sessions resource_manager_session = VI_ATTR_RM_SESSION interface_type = VI_ATTR_INTF_TYPE interface_number = VI_ATTR_INTF_NUM interface_instrument_name = VI_ATTR_INTF_INST_NAME resource_class = VI_ATTR_RSRC_CLASS resource_name = VI_ATTR_RSRC_NAME resource_impl_version = VI_ATTR_RSRC_IMPL_VERSION resource_lock_state = VI_ATTR_RSRC_LOCK_STATE resource_spec_version = VI_ATTR_RSRC_SPEC_VERSION resource_manufacturer_name = VI_ATTR_RSRC_MANF_NAME resource_manufacturer_id = VI_ATTR_RSRC_MANF_ID timeout_value = VI_ATTR_TMO_VALUE max_queue_length = VI_ATTR_MAX_QUEUE_LENGTH user_data = VI_ATTR_USER_DATA trigger_id = VI_ATTR_TRIG_ID # most resources no USB, nor TCPIP::SOCKET # Message based resource attributes send_end_enabled = VI_ATTR_SEND_END_EN suppress_end_enabled = VI_ATTR_SUPPRESS_END_EN termchar_enabled = VI_ATTR_TERMCHAR_EN termchar = VI_ATTR_TERMCHAR io_prot = VI_ATTR_IO_PROT file_append_enabled = VI_ATTR_FILE_APPEND_EN read_buffer_operation_mode = VI_ATTR_RD_BUF_OPER_MODE read_buffer_size = VI_ATTR_RD_BUF_SIZE write_buffer_operation_mode = VI_ATTR_WR_BUF_OPER_MODE write_buffer_size = VI_ATTR_WR_BUF_SIZE dma_allow_enabled = VI_ATTR_DMA_ALLOW_EN # TCPIP specific attributes tcpip_address = VI_ATTR_TCPIP_ADDR tcpip_hostname = VI_ATTR_TCPIP_HOSTNAME tcpip_port = VI_ATTR_TCPIP_PORT tcpip_device_name = VI_ATTR_TCPIP_DEVICE_NAME tcpip_nodelay = VI_ATTR_TCPIP_NODELAY tcpip_keepalive = VI_ATTR_TCPIP_KEEPALIVE tcpip_is_hislip = VI_ATTR_TCPIP_IS_HISLIP tcpip_hislip_version = VI_ATTR_TCPIP_HISLIP_VERSION tcpip_hislip_overlap_enable = VI_ATTR_TCPIP_HISLIP_OVERLAP_EN tcpip_hislip_max_message_kb = VI_ATTR_TCPIP_HISLIP_MAX_MESSAGE_KB # GPIB specific attributes gpib_primary_address = VI_ATTR_GPIB_PRIMARY_ADDR gpib_secondary_address = VI_ATTR_GPIB_SECONDARY_ADDR gpib_system_controller = VI_ATTR_GPIB_SYS_CNTRL_STATE gpib_cic_state = VI_ATTR_GPIB_CIC_STATE gpib_ren_state = VI_ATTR_GPIB_REN_STATE gpib_atn_state = VI_ATTR_GPIB_ATN_STATE gpib_ndac_state = VI_ATTR_GPIB_NDAC_STATE gpib_srq_state = VI_ATTR_GPIB_SRQ_STATE gpib_address_state = VI_ATTR_GPIB_ADDR_STATE gpib_unadress_enable = VI_ATTR_GPIB_UNADDR_EN gpib_readdress_enabled = VI_ATTR_GPIB_READDR_EN gpib_hs488_cable_length = VI_ATTR_GPIB_HS488_CBL_LEN # Serial specific attributes asrl_avalaible_number = VI_ATTR_ASRL_AVAIL_NUM asrl_baud_rate = VI_ATTR_ASRL_BAUD asrl_data_bits = VI_ATTR_ASRL_DATA_BITS asrl_parity = VI_ATTR_ASRL_PARITY asrl_stop_bits = VI_ATTR_ASRL_STOP_BITS asrl_flow_control = VI_ATTR_ASRL_FLOW_CNTRL asrl_discard_null = VI_ATTR_ASRL_DISCARD_NULL asrl_connected = VI_ATTR_ASRL_CONNECTED asrl_allow_transmit = VI_ATTR_ASRL_ALLOW_TRANSMIT asrl_end_in = VI_ATTR_ASRL_END_IN asrl_end_out = VI_ATTR_ASRL_END_OUT asrl_break_length = VI_ATTR_ASRL_BREAK_LEN asrl_break_state = VI_ATTR_ASRL_BREAK_STATE asrl_replace_char = VI_ATTR_ASRL_REPLACE_CHAR asrl_xon_char = VI_ATTR_ASRL_XON_CHAR asrl_xoff_char = VI_ATTR_ASRL_XOFF_CHAR asrl_cts_state = VI_ATTR_ASRL_CTS_STATE asrl_dsr_state = VI_ATTR_ASRL_DSR_STATE asrl_dtr_state = VI_ATTR_ASRL_DTR_STATE asrl_rts_state = VI_ATTR_ASRL_RTS_STATE asrl_wire_mode = VI_ATTR_ASRL_WIRE_MODE asrl_dcd_state = VI_ATTR_ASRL_DCD_STATE asrl_ri_state = VI_ATTR_ASRL_RI_STATE # USB specific attributes usb_interface_number = VI_ATTR_USB_INTFC_NUM usb_serial_number = VI_ATTR_USB_SERIAL_NUM usb_protocol = VI_ATTR_USB_PROTOCOL usb_max_interrupt_size = VI_ATTR_USB_MAX_INTR_SIZE usb_class = VI_ATTR_USB_CLASS usb_subclass = VI_ATTR_USB_SUBCLASS usb_bulk_in_status = VI_ATTR_USB_BULK_IN_STATUS usb_bulk_in_pipe = VI_ATTR_USB_BULK_IN_PIPE usb_bulk_out_status = VI_ATTR_USB_BULK_OUT_STATUS usb_bulk_out_pipe = VI_ATTR_USB_BULK_OUT_PIPE usb_interrupt_in_pipe = VI_ATTR_USB_INTR_IN_PIPE usb_alt_setting = VI_ATTR_USB_ALT_SETTING usb_end_in = VI_ATTR_USB_END_IN usb_number_interfaces = VI_ATTR_USB_NUM_INTFCS usb_number_pipes = VI_ATTR_USB_NUM_PIPES usb_interrupt_in_status = VI_ATTR_USB_INTR_IN_STATUS usb_control_pipe = VI_ATTR_USB_CTRL_PIPE # USB, VXI, GPIB-VXI, PXI specific attributes manufacturer_name = VI_ATTR_MANF_NAME manufacturer_id = VI_ATTR_MANF_ID model_name = VI_ATTR_MODEL_NAME model_code = VI_ATTR_MODEL_CODE # GPIB INTFC, VXI SERVANT device_status_byte = VI_ATTR_DEV_STATUS_BYTE # (USB, VXI, GPIB-VXI)::INSTR specific attributes is_4882_compliant = VI_ATTR_4882_COMPLIANT # (VXI, GPIB-VXI and PXI)::INSTR specific attributes slot = VI_ATTR_SLOT window_access = VI_ATTR_WIN_ACCESS window_base_address = VI_ATTR_WIN_BASE_ADDR window_size = VI_ATTR_WIN_SIZE source_increment = VI_ATTR_SRC_INCREMENT destination_increment = VI_ATTR_DEST_INCREMENT # VXI and GPIB-VXI specific attributes fdc_channel = VI_ATTR_FDC_CHNL fdc_mode = VI_ATTR_FDC_MODE fdc_generate_signal_enabled = VI_ATTR_FDC_GEN_SIGNAL_EN fdc_use_pair = VI_ATTR_FDC_USE_PAIR mainframe_logical_address = VI_ATTR_MAINFRAME_LA vxi_logical_address = VI_ATTR_VXI_LA commander_logical_address = VI_ATTR_CMDR_LA memory_space = VI_ATTR_MEM_SPACE memory_size = VI_ATTR_MEM_SIZE memory_base = VI_ATTR_MEM_BASE immediate_servant = VI_ATTR_IMMEDIATE_SERV destination_access_private = VI_ATTR_DEST_ACCESS_PRIV destination_byte_order = VI_ATTR_DEST_BYTE_ORDER source_access_private = VI_ATTR_SRC_ACCESS_PRIV source_byte_order = VI_ATTR_SRC_BYTE_ORDER window_access_private = VI_ATTR_WIN_ACCESS_PRIV window_byte_order = VI_ATTR_WIN_BYTE_ORDER vxi_trigger_support = VI_ATTR_VXI_TRIG_SUPPORT # GPIB-VXI specific attributes interface_parent_number = VI_ATTR_INTF_PARENT_NUM # VXI specific attributes vxi_device_class = VI_ATTR_VXI_DEV_CLASS # INSTR vxi_trig_dir = VI_ATTR_VXI_TRIG_DIR # INSTR vxi_trig_lines_enabled = VI_ATTR_VXI_TRIG_LINES_EN # INSTR vxi_vme_interrupt_status = VI_ATTR_VXI_VME_INTR_STATUS # BACKPLANE vxi_trigger_status = VI_ATTR_VXI_TRIG_STATUS # BACKPLANE vxi_vme_sysfail_state = VI_ATTR_VXI_VME_SYSFAIL_STATE # BACKPLANE # PXI specific attributes pxi_device_number = VI_ATTR_PXI_DEV_NUM pxi_function_num = VI_ATTR_PXI_FUNC_NUM pxi_bus_number = VI_ATTR_PXI_BUS_NUM pxi_chassis = VI_ATTR_PXI_CHASSIS pxi_slotpath = VI_ATTR_PXI_SLOTPATH pxi_slot_lbus_left = VI_ATTR_PXI_SLOT_LBUS_LEFT pxi_slot_lbus_right = VI_ATTR_PXI_SLOT_LBUS_RIGHT pxi_is_express = VI_ATTR_PXI_IS_EXPRESS pxi_slot_lwidth = VI_ATTR_PXI_SLOT_LWIDTH pxi_max_ldwidth = VI_ATTR_PXI_MAX_LWIDTH pxi_actual_ldwidth = VI_ATTR_PXI_ACTUAL_LWIDTH pxi_dstar_bus = VI_ATTR_PXI_DSTAR_BUS pxi_dstar_set = VI_ATTR_PXI_DSTAR_SET pxi_trig_bus = VI_ATTR_PXI_TRIG_BUS pxi_star_trig_bus = VI_ATTR_PXI_STAR_TRIG_BUS pxi_star_trig_line = VI_ATTR_PXI_STAR_TRIG_LINE pxi_source_trigger_bus = VI_ATTR_PXI_SRC_TRIG_BUS pxi_destination_trigger_bus = VI_ATTR_PXI_DEST_TRIG_BUS # PXI BAR memory scpecific attributes pxi_memory_type_bar0 = VI_ATTR_PXI_MEM_TYPE_BAR0 pxi_memory_type_bar1 = VI_ATTR_PXI_MEM_TYPE_BAR1 pxi_memory_type_bar2 = VI_ATTR_PXI_MEM_TYPE_BAR2 pxi_memory_type_bar3 = VI_ATTR_PXI_MEM_TYPE_BAR3 pxi_memory_type_bar4 = VI_ATTR_PXI_MEM_TYPE_BAR4 pxi_memory_type_bar5 = VI_ATTR_PXI_MEM_TYPE_BAR5 pxi_memory_base_bar0 = VI_ATTR_PXI_MEM_BASE_BAR0 pxi_memory_base_bar1 = VI_ATTR_PXI_MEM_BASE_BAR1 pxi_memory_base_bar2 = VI_ATTR_PXI_MEM_BASE_BAR2 pxi_memory_base_bar3 = VI_ATTR_PXI_MEM_BASE_BAR3 pxi_memory_base_bar4 = VI_ATTR_PXI_MEM_BASE_BAR4 pxi_memory_base_bar5 = VI_ATTR_PXI_MEM_BASE_BAR5 pxi_memory_size_bar0 = VI_ATTR_PXI_MEM_SIZE_BAR0 pxi_memory_size_bar1 = VI_ATTR_PXI_MEM_SIZE_BAR1 pxi_memory_size_bar2 = VI_ATTR_PXI_MEM_SIZE_BAR2 pxi_memory_size_bar3 = VI_ATTR_PXI_MEM_SIZE_BAR3 pxi_memory_size_bar4 = VI_ATTR_PXI_MEM_SIZE_BAR4 pxi_memory_size_bar5 = VI_ATTR_PXI_MEM_SIZE_BAR5 pyvisa-1.11.3/pyvisa/ctwrapper/000077500000000000000000000000001375165327600164515ustar00rootroot00000000000000pyvisa-1.11.3/pyvisa/ctwrapper/__init__.py000066400000000000000000000006711375165327600205660ustar00rootroot00000000000000# -*- coding: utf-8 -*- """ctypes wrapper for IVI-VISA library. This file is part of PyVISA. :copyright: 2014-2019 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ import os from .highlevel import IVIVisaLibrary WRAPPER_CLASS = IVIVisaLibrary WRAP_HANDLER = True env_value = os.environ.get("PYVISA_WRAP_HANDLER", None) if env_value is not None: WRAP_HANDLER = bool(int(env_value)) pyvisa-1.11.3/pyvisa/ctwrapper/cthelper.py000066400000000000000000000047411375165327600206370ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Cross platform helper of ctypes. This file is part of PyVISA. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ import ctypes import os import sys if sys.platform == "win32": FUNCTYPE, Library = ctypes.WINFUNCTYPE, ctypes.WinDLL else: FUNCTYPE, Library = ctypes.CFUNCTYPE, ctypes.CDLL # On Linux, find Library returns the name not the path. # This excerpt provides a modified find_library. if os.name == "posix" and sys.platform.startswith("linux"): # Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump def define_find_libary(): import errno import re import tempfile def _findlib_gcc(name): expr = r"[^\(\)\s]*lib%s\.[^\(\)\s]*" % re.escape(name) fdout, ccout = tempfile.mkstemp() os.close(fdout) cmd = ( "if type gcc >/dev/null 2>&1; then CC=gcc; else CC=cc; fi;" "$CC -Wl,-t -o " + ccout + " 2>&1 -l" + name ) trace = "" try: f = os.popen(cmd) trace = f.read() f.close() finally: try: os.unlink(ccout) except OSError as e: if e.errno != errno.ENOENT: raise res = re.search(expr, trace) if not res: return None return res.group(0) def _findlib_ldconfig(name): # NOTE: assuming GLIBC's ldconfig (with option -p) expr = r"/[^\(\)\s]*lib%s\.[^\(\)\s]*" % re.escape(name) with os.popen("/sbin/ldconfig -p 2>/dev/null") as pipe: res = re.search(expr, pipe.read()) if not res: # Hm, this works only for libs needed by the python executable. cmd = "ldd %s 2>/dev/null" % sys.executable with os.popen(cmd) as pipe: res = re.search(expr, pipe.read()) if not res: return None return res.group(0) def _find_library(name): path = _findlib_ldconfig(name) or _findlib_gcc(name) if path: return os.path.realpath(path) return path return _find_library find_library = define_find_libary() else: from ctypes.util import find_library __all__ = ["find_library", "FUNCTYPE", "Library"] pyvisa-1.11.3/pyvisa/ctwrapper/functions.py000066400000000000000000002473621375165327600210510ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Defines VPP 4.3.2 wrapping functions using ctypes, adding signatures to the library. This file is part of PyVISA. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ import warnings from contextlib import contextmanager from ctypes import ( POINTER, byref, c_double, c_long, c_void_p, c_wchar_p, create_string_buffer, ) from functools import update_wrapper from threading import Lock from typing import Any, Callable, Optional, Tuple from pyvisa import attributes, constants, ctwrapper, typing from pyvisa.highlevel import ResourceInfo from . import types from .types import ( FUNCTYPE, ViAccessMode, ViAChar, ViAddr, ViAttr, ViAttrState, ViAUInt8, ViAUInt16, ViAUInt32, ViAUInt64, ViBoolean, ViBuf, ViBusAddress, ViBusAddress64, ViBusSize, ViEvent, ViEventFilter, ViEventType, ViFindList, ViHndlr, ViInt16, ViJobId, ViKeyId, ViObject, ViPAddr, ViPBuf, ViPBusAddress, ViPEvent, ViPEventType, ViPFindList, ViPJobId, ViPSession, ViPUInt8, ViPUInt16, ViPUInt32, ViPUInt64, ViRsrc, ViSession, ViStatus, ViString, ViUInt8, ViUInt16, ViUInt32, ViUInt64, buffer_to_text, ) visa_functions = [ "assert_interrupt_signal", "assert_trigger", "assert_utility_signal", "buffer_read", "buffer_write", "clear", "close", "disable_event", "discard_events", "enable_event", "_find_next", "_find_resources", "flush", "get_attribute", "gpib_command", "gpib_control_atn", "gpib_control_ren", "gpib_pass_control", "gpib_send_ifc", "in_16", "in_32", "in_8", "install_handler", "lock", "map_address", "map_trigger", "memory_allocation", "memory_free", "move", "move_asynchronously", "move_in_16", "move_in_32", "move_in_8", "move_out_16", "move_out_32", "move_out_8", "open", "open_default_resource_manager", "out_16", "out_32", "out_8", "parse_resource", "parse_resource_extended", "peek_16", "peek_32", "peek_8", "poke_16", "poke_32", "poke_8", "read", "read_to_file", "read_stb", "set_attribute", "set_buffer", "status_description", "terminate", "uninstall_handler", "unlock", "unmap_address", "unmap_trigger", "usb_control_in", "usb_control_out", "vxi_command_query", "wait_on_event", "write", "write_asynchronously", "write_from_file", "in_64", "move_in_64", "out_64", "move_out_64", "poke_64", "peek_64", ] __all__ = ["visa_functions", "set_signatures"] + visa_functions VI_SPEC_VERSION = 0x00300000 #: Global lock to ensure that we cannot have one thread change the type while #: another is trying to interact with VISA ViHndlr_lock = Lock() @contextmanager def set_user_handle_type(library, user_handle: Any): """Set the type of the user handle to install and uninstall handler signature. Parameters ---------- library : The visa library wrapped by ctypes. user_handle : User handle used when registering an event handler. Use None for a void_p. """ with ViHndlr_lock: # Actually, it's not necessary to change ViHndlr *globally*. However, # I don't want to break symmetry too much with all the other VPP43 # routines. global ViHndlr if user_handle is None: user_handle_p = c_void_p else: user_handle_p = POINTER(type(user_handle)) # type: ignore ViHndlr = FUNCTYPE(ViStatus, ViSession, ViEventType, ViEvent, user_handle_p) library.viInstallHandler.argtypes = [ ViSession, ViEventType, ViHndlr, user_handle_p, ] library.viUninstallHandler.argtypes = [ ViSession, ViEventType, ViHndlr, user_handle_p, ] yield def set_signatures( library, errcheck: Optional[Callable[[int, Callable, tuple], int]] = None ): """Set the signatures of most visa functions in the library. All instrumentation related functions are specified here. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL The visa library wrapped by ctypes. errcheck : Optional[Callable[[int, Callable, tuple], int]] Error checking callable used for visa functions that return ViStatus. It should be take three arguments (result, func, arguments). See errcheck in ctypes. """ # Somehow hasattr(library, '_functions') segfaults in cygwin (See #131) if "_functions" not in dir(library): library._functions = [] library._functions_failed = [] def _applier(restype, errcheck_): def _internal(function_name, argtypes, required=False): try: set_signature(library, function_name, argtypes, restype, errcheck_) library._functions.append(function_name) except AttributeError: library._functions_failed.append(function_name) if required: raise return _internal # Visa functions with ViStatus return code apply = _applier(ViStatus, errcheck) apply("viAssertIntrSignal", [ViSession, ViInt16, ViUInt32]) apply("viAssertTrigger", [ViSession, ViUInt16]) apply("viAssertUtilSignal", [ViSession, ViUInt16]) apply("viBufRead", [ViSession, ViPBuf, ViUInt32, ViPUInt32]) apply("viBufWrite", [ViSession, ViBuf, ViUInt32, ViPUInt32]) apply("viClear", [ViSession]) apply("viClose", [ViObject]) apply("viDisableEvent", [ViSession, ViEventType, ViUInt16]) apply("viDiscardEvents", [ViSession, ViEventType, ViUInt16]) apply("viEnableEvent", [ViSession, ViEventType, ViUInt16, ViEventFilter]) apply("viFindNext", [ViSession, ViAChar]) apply("viFindRsrc", [ViSession, ViString, ViPFindList, ViPUInt32, ViAChar]) apply("viFlush", [ViSession, ViUInt16]) apply("viGetAttribute", [ViObject, ViAttr, c_void_p]) apply("viGpibCommand", [ViSession, ViBuf, ViUInt32, ViPUInt32]) apply("viGpibControlATN", [ViSession, ViUInt16]) apply("viGpibControlREN", [ViSession, ViUInt16]) apply("viGpibPassControl", [ViSession, ViUInt16, ViUInt16]) apply("viGpibSendIFC", [ViSession]) apply("viIn8", [ViSession, ViUInt16, ViBusAddress, ViPUInt8]) apply("viIn16", [ViSession, ViUInt16, ViBusAddress, ViPUInt16]) apply("viIn32", [ViSession, ViUInt16, ViBusAddress, ViPUInt32]) apply("viIn64", [ViSession, ViUInt16, ViBusAddress, ViPUInt64]) apply("viIn8Ex", [ViSession, ViUInt16, ViBusAddress64, ViPUInt8]) apply("viIn16Ex", [ViSession, ViUInt16, ViBusAddress64, ViPUInt16]) apply("viIn32Ex", [ViSession, ViUInt16, ViBusAddress64, ViPUInt32]) apply("viIn64Ex", [ViSession, ViUInt16, ViBusAddress64, ViPUInt64]) apply("viInstallHandler", [ViSession, ViEventType, ViHndlr, ViAddr]) apply("viLock", [ViSession, ViAccessMode, ViUInt32, ViKeyId, ViAChar]) apply( "viMapAddress", [ViSession, ViUInt16, ViBusAddress, ViBusSize, ViBoolean, ViAddr, ViPAddr], ) apply("viMapTrigger", [ViSession, ViInt16, ViInt16, ViUInt16]) apply("viMemAlloc", [ViSession, ViBusSize, ViPBusAddress]) apply("viMemFree", [ViSession, ViBusAddress]) apply( "viMove", [ ViSession, ViUInt16, ViBusAddress, ViUInt16, ViUInt16, ViBusAddress, ViUInt16, ViBusSize, ], ) apply( "viMoveAsync", [ ViSession, ViUInt16, ViBusAddress, ViUInt16, ViUInt16, ViBusAddress, ViUInt16, ViBusSize, ViPJobId, ], ) apply("viMoveIn8", [ViSession, ViUInt16, ViBusAddress, ViBusSize, ViAUInt8]) apply("viMoveIn16", [ViSession, ViUInt16, ViBusAddress, ViBusSize, ViAUInt16]) apply("viMoveIn32", [ViSession, ViUInt16, ViBusAddress, ViBusSize, ViAUInt32]) apply("viMoveIn64", [ViSession, ViUInt16, ViBusAddress, ViBusSize, ViAUInt64]) apply("viMoveIn8Ex", [ViSession, ViUInt16, ViBusAddress64, ViBusSize, ViAUInt8]) apply("viMoveIn16Ex", [ViSession, ViUInt16, ViBusAddress64, ViBusSize, ViAUInt16]) apply("viMoveIn32Ex", [ViSession, ViUInt16, ViBusAddress64, ViBusSize, ViAUInt32]) apply("viMoveIn64Ex", [ViSession, ViUInt16, ViBusAddress64, ViBusSize, ViAUInt64]) apply("viMoveOut8", [ViSession, ViUInt16, ViBusAddress, ViBusSize, ViAUInt8]) apply("viMoveOut16", [ViSession, ViUInt16, ViBusAddress, ViBusSize, ViAUInt16]) apply("viMoveOut32", [ViSession, ViUInt16, ViBusAddress, ViBusSize, ViAUInt32]) apply("viMoveOut64", [ViSession, ViUInt16, ViBusAddress, ViBusSize, ViAUInt64]) apply("viMoveOut8Ex", [ViSession, ViUInt16, ViBusAddress64, ViBusSize, ViAUInt8]) apply("viMoveOut16Ex", [ViSession, ViUInt16, ViBusAddress64, ViBusSize, ViAUInt16]) apply("viMoveOut32Ex", [ViSession, ViUInt16, ViBusAddress64, ViBusSize, ViAUInt32]) apply("viMoveOut64Ex", [ViSession, ViUInt16, ViBusAddress64, ViBusSize, ViAUInt64]) apply( "viOpen", [ViSession, ViRsrc, ViAccessMode, ViUInt32, ViPSession], required=True ) apply("viOpenDefaultRM", [ViPSession], required=True) apply("viOut8", [ViSession, ViUInt16, ViBusAddress, ViUInt8]) apply("viOut16", [ViSession, ViUInt16, ViBusAddress, ViUInt16]) apply("viOut32", [ViSession, ViUInt16, ViBusAddress, ViUInt32]) apply("viOut64", [ViSession, ViUInt16, ViBusAddress, ViUInt64]) apply("viOut8Ex", [ViSession, ViUInt16, ViBusAddress64, ViUInt8]) apply("viOut16Ex", [ViSession, ViUInt16, ViBusAddress64, ViUInt16]) apply("viOut32Ex", [ViSession, ViUInt16, ViBusAddress64, ViUInt32]) apply("viOut64Ex", [ViSession, ViUInt16, ViBusAddress64, ViUInt64]) apply("viParseRsrc", [ViSession, ViRsrc, ViPUInt16, ViPUInt16]) apply( "viParseRsrcEx", [ViSession, ViRsrc, ViPUInt16, ViPUInt16, ViAChar, ViAChar, ViAChar], ) apply("viRead", [ViSession, ViPBuf, ViUInt32, ViPUInt32]) apply("viReadAsync", [ViSession, ViPBuf, ViUInt32, ViPJobId]) apply("viReadSTB", [ViSession, ViPUInt16]) apply("viReadToFile", [ViSession, ViString, ViUInt32, ViPUInt32]) apply("viSetAttribute", [ViObject, ViAttr, ViAttrState]) apply("viSetBuf", [ViSession, ViUInt16, ViUInt32]) apply("viStatusDesc", [ViObject, ViStatus, ViAChar]) apply("viTerminate", [ViSession, ViUInt16, ViJobId]) apply("viUninstallHandler", [ViSession, ViEventType, ViHndlr, ViAddr]) apply("viUnlock", [ViSession]) apply("viUnmapAddress", [ViSession]) apply("viUnmapTrigger", [ViSession, ViInt16, ViInt16]) apply( "viUsbControlIn", [ViSession, ViInt16, ViInt16, ViUInt16, ViUInt16, ViUInt16, ViPBuf, ViPUInt16], ) apply( "viUsbControlOut", [ViSession, ViInt16, ViInt16, ViUInt16, ViUInt16, ViUInt16, ViPBuf], ) # The following "V" routines are *not* implemented in PyVISA, and will # never be: viVPrintf, viVQueryf, viVScanf, viVSPrintf, viVSScanf apply("viVxiCommandQuery", [ViSession, ViUInt16, ViUInt32, ViPUInt32]) apply("viWaitOnEvent", [ViSession, ViEventType, ViUInt32, ViPEventType, ViPEvent]) apply("viWrite", [ViSession, ViBuf, ViUInt32, ViPUInt32]) apply("viWriteAsync", [ViSession, ViBuf, ViUInt32, ViPJobId]) apply("viWriteFromFile", [ViSession, ViString, ViUInt32, ViPUInt32]) # Functions that return void. apply = _applier(None, None) apply("viPeek8", [ViSession, ViAddr, ViPUInt8]) apply("viPeek16", [ViSession, ViAddr, ViPUInt16]) apply("viPeek32", [ViSession, ViAddr, ViPUInt32]) apply("viPeek64", [ViSession, ViAddr, ViPUInt64]) apply("viPoke8", [ViSession, ViAddr, ViUInt8]) apply("viPoke16", [ViSession, ViAddr, ViUInt16]) apply("viPoke32", [ViSession, ViAddr, ViUInt32]) apply("viPoke64", [ViSession, ViAddr, ViUInt64]) def set_signature( library, function_name: str, argtypes: tuple, restype, errcheck: Optional[Callable[[int, Callable, tuple], int]], ): """Set the signature of single function in a library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. function_name : str Name of the function as appears in the header file. argtypes : tuple ctypes types to specify the argument types that the function accepts. restype : A ctypes type to specify the result type of the foreign function. Use None for void, a function not returning anything. errcheck : Optional[Callable[[int, Callable, tuple], int]] Error checking callable used for visa functions that return ViStatus. It should be take three arguments (result, func, arguments). See errcheck in ctypes. """ func = getattr(library, function_name) func.argtypes = argtypes if restype is not None: func.restype = restype if errcheck is not None: func.errcheck = errcheck # The VPP-4.3.2 routines # Usually, there is more than one way to pass parameters to ctypes calls. The # ctypes policy used in this code goes as follows: # # * Null pointers are passed as "None" rather than "0". This is a little bit # unfortunate, since the VPP specification calls this "VI_NULL", but I can't # use "VI_NULL" since it's an integer and may not be compatible with a # pointer type (don't know whether this is really dangerous). # # * Strings must have been created with "create_string_buffer" and are passed # without any further conversion; they stand in the parameter list as is. # The same applies to pseudo-string types as ViRsrc or VuBuf. Their Pythonic # counterpats are strings as well. # # * All other types are explicitly cast using the types defined by ctypes' # "restype". # # Further notes: # # * The following Python routines take and give handles as ctypes objects. # Since the user shouldn't be interested in handle values anyway, I see no # point in converting them to Python strings or integers. # # * All other parameters are natural Python types, i.e. strings (may contain # binary data) and integers. The same is true for return values. # # * The original VPP function signatures cannot be realised in Python, at least # not in a sensible way, because a) Python has no real call-by-reference, and # b) Python allows for more elegant solutions, e.g. using len(buffer) instead # of a separate "count" parameter, or using tuples as return values. # # Therefore, all function signatures have been carefully adjusted. I think # this is okay, since the original standard must be adopted to at least C and # Visual Basic anyway, with slight modifications. I also made the function # names and parameters more legible, but in a way that it's perfectly clear # which original function is meant. # # The important thing is that the semantics of functions and parameters are # totally intact, and the inner order of parameters, too. There is a 1:1 # mapping. def assert_interrupt_signal(library, session, mode, status_id): """Asserts the specified interrupt or signal. Corresponds to viAssertIntrSignal function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. mode : constants.AssertSignalInterrupt How to assert the interrupt. status_id : int Status value to be presented during an interrupt acknowledge cycle. Returns ------- constants.StatusCode Return value of the library call. """ return library.viAssertIntrSignal(session, mode, status_id) def assert_trigger(library, session, protocol): """Assert software or hardware trigger. Corresponds to viAssertTrigger function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. protocol : constants.TriggerProtocol Trigger protocol to use during assertion. Returns ------- constants.StatusCode Return value of the library call. """ return library.viAssertTrigger(session, protocol) def assert_utility_signal(library, session, line): """Assert or deassert the specified utility bus signal. Corresponds to viAssertUtilSignal function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. line : constants.UtilityBusSignal Specifies the utility bus signal to assert. Returns ------- constants.StatusCode Return value of the library call. """ return library.viAssertUtilSignal(session, line) def buffer_read(library, session, count): """Reads data through the use of a formatted I/O read buffer. The data can be read from a device or an interface. Corresponds to viBufRead function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. count : int Number of bytes to be read. Returns ------- dbytes Data read constants.StatusCode Return value of the library call. """ buffer = create_string_buffer(count) return_count = ViUInt32() ret = library.viBufRead(session, buffer, count, byref(return_count)) return buffer.raw[: return_count.value], ret def buffer_write(library, session, data): """Writes data to a formatted I/O write buffer synchronously. Corresponds to viBufWrite function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. data : bytes Data to be written. Returns ------- int number of written bytes constants.StatusCode return value of the library call. """ return_count = ViUInt32() # [ViSession, ViBuf, ViUInt32, ViPUInt32] ret = library.viBufWrite(session, data, len(data), byref(return_count)) return return_count.value, ret def clear(library, session): """Clears a device. Corresponds to viClear function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. Returns ------- constants.StatusCode Return value of the library call. """ return library.viClear(session) def close(library, session): """Closes the specified session, event, or find list. Corresponds to viClose function of the VISA library. Parameters --------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : Union[VISASession, VISAEventContext, VISARMSession] Unique logical identifier to a session, event, resource manager. Returns ------- constants.StatusCode Return value of the library call. """ return library.viClose(session) def disable_event(library, session, event_type, mechanism): """Disable notification for an event type(s) via the specified mechanism(s). Corresponds to viDisableEvent function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. event_type : constants.EventType Event type. mechanism : constants.EventMechanism Event handling mechanisms to be disabled. Returns ------- constants.StatusCode Return value of the library call. """ return library.viDisableEvent(session, event_type, mechanism) def discard_events(library, session, event_type, mechanism): """Discard event occurrences for a given type and mechanisms in a session. Corresponds to viDiscardEvents function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. event_type : constans.EventType Logical event identifier. mechanism : constants.EventMechanism Specifies event handling mechanisms to be discarded. Returns ------- constants.StatusCode Return value of the library call. """ return library.viDiscardEvents(session, event_type, mechanism) def enable_event(library, session, event_type, mechanism, context=None): """Enable event occurrences for specified event types and mechanisms in a session. Corresponds to viEnableEvent function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. event_type : constants.EventType Logical event identifier. mechanism : constants.EventMechanism Specifies event handling mechanisms to be enabled. context : None, optional Unused parameter... Returns ------- constants.StatusCode Return value of the library call. """ if context is None: context = constants.VI_NULL elif context != constants.VI_NULL: warnings.warn("In enable_event, context will be set VI_NULL.") context = constants.VI_NULL # according to spec VPP-4.3, section 3.7.3.1 return library.viEnableEvent(session, event_type, mechanism, context) def _find_next(library, find_list: ViFindList) -> Tuple[str, constants.StatusCode]: """Get next resource from the list of resources. The list of resources should be obtained from a previous call to find_resources(). Corresponds to viFindNext function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. find_list : Describes a find list. This parameter must be created by find_resources(). Returns ------- str String identifying the location of a device constants.StatusCode Return value of the library call. """ instrument_description = create_string_buffer(constants.VI_FIND_BUFLEN) ret = library.viFindNext(find_list, instrument_description) return buffer_to_text(instrument_description), ret def _find_resources(library, session: typing.VISARMSession, query: str): """Queries VISA to locate the resources associated with a specified interface. Corresponds to viFindRsrc function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : typing.VISARMSession Unique logical identifier to the ResourceManger session (unused, just to uniform signatures). query : str A regular expression followed by an optional logical expression. Use '?*' for all. Returns ------- ViFindList Opaque object to pass to `_find_next` to access the other devices resource name. int Number of identified devices. str Resource name of the first identified device constants.StatusCode Return value of the library call. """ find_list = ViFindList() return_counter = ViUInt32() instrument_description = create_string_buffer(constants.VI_FIND_BUFLEN) ret = library.viFindRsrc( session, query, byref(find_list), byref(return_counter), instrument_description ) return find_list, return_counter.value, buffer_to_text(instrument_description), ret def flush(library, session, mask): """Retrieves the state of an attribute. Corresponds to viGetAttribute function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : Union[VISASession, VISAEventContext] Unique logical identifier to a session, event, or find list. attribute : Union[constants.ResourceAttribute, constants.EventAttribute] Resource or event attribute for which the state query is made. Returns ------- Any State of the queried attribute for a specified resource constants.StatusCode Return value of the library call. """ return library.viFlush(session, mask) def get_attribute(library, session, attribute): """Retrieves the state of an attribute. Corresponds to viGetAttribute function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : Union[VISASession, VISAEventContext] Unique logical identifier to a session, event, or find list. attribute : Union[constants.ResourceAttribute, constants.EventAttribute] Resource or event attribute for which the state query is made. Returns ------- Any State of the queried attribute for a specified resource constants.StatusCode Return value of the library call. """ attr = attributes.AttributesByID[attribute] datatype = getattr(types, attr.visa_type) if datatype == ViString: attribute_state = create_string_buffer(256) ret = library.viGetAttribute(session, attribute, attribute_state) return buffer_to_text(attribute_state), ret # There are only 2 buffer attribute, the one we do not handle if the one # to async read that is handled at a higher since we pass the buffer ourself elif datatype == ViBuf: if attr.visa_name == "VI_ATTR_USB_RECV_INTR_DATA": length = get_attribute( library, session, constants.VI_ATTR_USB_RECV_INTR_SIZE ) attribute_state = (ViUInt8 * length)() ret = library.viGetAttribute(session, attribute, byref(attribute_state)) return list(attribute_state), ret else: raise AttributeError("%s cannot be accessed directly" % attr.visa_name) else: attribute_state = datatype() ret = library.viGetAttribute(session, attribute, byref(attribute_state)) return attribute_state.value, ret def gpib_command(library, session, data): """Write GPIB command bytes on the bus. Corresponds to viGpibCommand function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. data : bytes Data to write. Returns ------- int Number of written bytes constants.StatusCode Return value of the library call. """ return_count = ViUInt32() # [ViSession, ViBuf, ViUInt32, ViPUInt32] ret = library.viGpibCommand(session, data, len(data), byref(return_count)) return return_count.value, ret def gpib_control_atn(library, session, mode): """Specifies the state of the ATN line and the local active controller state. Corresponds to viGpibControlATN function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. mode : constants.ATNLineOperation State of the ATN line and optionally the local active controller state. Returns ------- constants.StatusCode Return value of the library call. """ return library.viGpibControlATN(session, mode) def gpib_control_ren(library, session, mode): """Controls the state of the GPIB Remote Enable (REN) interface line. Optionally the remote/local state of the device can also be set. Corresponds to viGpibControlREN function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. mode : constants.RENLineOperation State of the REN line and optionally the device remote/local state. Returns ------- constants.StatusCode Return value of the library call. """ return library.viGpibControlREN(session, mode) def gpib_pass_control(library, session, primary_address, secondary_address): """Tell a GPIB device to become controller in charge (CIC). Corresponds to viGpibPassControl function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. primary_address : int Primary address of the GPIB device to which you want to pass control. secondary_address : int Secondary address of the targeted GPIB device. If the targeted device does not have a secondary address, this parameter should contain the value Constants.VI_NO_SEC_ADDR. Returns ------- constants.StatusCode Return value of the library call. """ return library.viGpibPassControl(session, primary_address, secondary_address) def gpib_send_ifc(library, session): """Pulse the interface clear line (IFC) for at least 100 microseconds. Corresponds to viGpibSendIFC function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. Returns ------- constants.StatusCode Return value of the library call. """ return library.viGpibSendIFC(session) def in_8(library, session, space, offset, extended=False): """Reads in an 8-bit value from the specified memory space and offset. Corresponds to viIn8* function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Specifies the address space. offset : int Offset (in bytes) of the address or register from which to read. extended : bool, optional Use 64 bits offset independent of the platform, False by default. Returns ------- int Data read from memory constants.StatusCode Return value of the library call. """ value_8 = ViUInt8() if extended: ret = library.viIn8Ex(session, space, offset, byref(value_8)) else: ret = library.viIn8(session, space, offset, byref(value_8)) return value_8.value, ret def in_16(library, session, space, offset, extended=False): """Reads in an 16-bit value from the specified memory space and offset. Corresponds to viIn16* function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Specifies the address space. offset : int Offset (in bytes) of the address or register from which to read. extended : bool, optional Use 64 bits offset independent of the platform, False by default. Returns ------- int Data read from memory constants.StatusCode Return value of the library call. """ value_16 = ViUInt16() if extended: ret = library.viIn16Ex(session, space, offset, byref(value_16)) else: ret = library.viIn16(session, space, offset, byref(value_16)) return value_16.value, ret def in_32(library, session, space, offset, extended=False): """Reads in an 32-bit value from the specified memory space and offset. Corresponds to viIn32* function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Specifies the address space. offset : int Offset (in bytes) of the address or register from which to read. extended : bool, optional Use 64 bits offset independent of the platform, False by default. Returns ------- int Data read from memory constants.StatusCode Return value of the library call. """ value_32 = ViUInt32() if extended: ret = library.viIn32Ex(session, space, offset, byref(value_32)) else: ret = library.viIn32(session, space, offset, byref(value_32)) return value_32.value, ret def in_64(library, session, space, offset, extended=False): """Reads in an 64-bit value from the specified memory space and offset. Corresponds to viIn64* function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Specifies the address space. offset : int Offset (in bytes) of the address or register from which to read. extended : bool, optional Use 64 bits offset independent of the platform, False by default. Returns ------- int Data read from memory constants.StatusCode Return value of the library call. """ value_64 = ViUInt64() if extended: ret = library.viIn64Ex(session, space, offset, byref(value_64)) else: ret = library.viIn64(session, space, offset, byref(value_64)) return value_64.value, ret def install_handler( library, session, event_type, handler, user_handle: Any ) -> Tuple[typing.VISAHandler, Any, Any, constants.StatusCode]: """Install handlers for event callbacks. Corresponds to viInstallHandler function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. event_type : constants.EventType Logical event identifier. handler : VISAHandler Reference to a handler to be installed by a client application. user_handle : Any Value specified by an application that can be used for identifying handlers uniquely for an event type. Returns ------- handler : VISAHandler Handler to be installed by a client application. converted_user_handle : Converted user handle to match the underlying library. This version of the handle should be used in further call to the library. converted_handler : Converted version of the handler satisfying to backend library. status_code : constants.StatusCode Return value of the library call """ # Should be Optional[_CData] but that type cannot be imported converted_user_handle: object = None if user_handle is not None: if isinstance(user_handle, int): converted_user_handle = c_long(user_handle) elif isinstance(user_handle, float): converted_user_handle = c_double(user_handle) elif isinstance(user_handle, str): converted_user_handle = c_wchar_p(user_handle) elif isinstance(user_handle, list): for element in user_handle: if not isinstance(element, int): # Mypy cannot track the fact that the list has to contain float converted_user_handle = (c_double * len(user_handle))( # type: ignore *tuple(user_handle) ) break else: converted_user_handle = (c_long * len(user_handle))(*tuple(user_handle)) else: try: # check if it is already a ctypes byref(user_handle) converted_user_handle = user_handle except TypeError: raise TypeError( "Type not allowed as user handle: %s" % type(user_handle) ) with set_user_handle_type(library, converted_user_handle): if ctwrapper.WRAP_HANDLER: # Wrap the handler to provide a non-wrapper specific interface def handler_wrapper( ctype_session, ctype_event_type, ctype_event_context, ctype_user_handle ): handler( ctype_session.value, ctype_event_type, ctype_event_context.value, ctype_user_handle.contents if ctype_user_handle else ctype_user_handle, ) return 0 update_wrapper(handler_wrapper, handler) else: handler_wrapper = handler converted_handler = ViHndlr(handler_wrapper) if user_handle is None: ret = library.viInstallHandler(session, event_type, converted_handler, None) else: ret = library.viInstallHandler( session, event_type, converted_handler, byref(converted_user_handle), # type: ignore ) return handler, converted_user_handle, converted_handler, ret def lock(library, session, lock_type, timeout, requested_key=None): """Establishes an access mode to the specified resources. Corresponds to viLock function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. lock_type : constants.Lock Specifies the type of lock requested. timeout : int Absolute time period (in milliseconds) that a resource waits to get unlocked by the locking session before returning an error. requested_key : Optional[str], optional Requested locking key in the case of a shared lock. For an exclusive lock it should be None. Returns ------- Optional[str] Key that can then be passed to other sessions to share the lock, or None for an exclusive lock. constants.StatusCode Return value of the library call. """ if lock_type == constants.AccessModes.exclusive_lock: requested_key = None access_key = None else: access_key = create_string_buffer(256) ret = library.viLock(session, lock_type, timeout, requested_key, access_key) if access_key is None: return None, ret else: return access_key.value, ret def map_address( library, session, map_space, map_base, map_size, access=False, suggested=None ): """Maps the specified memory space into the process's address space. Corresponds to viMapAddress function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. map_space : constants.AddressSpace Specifies the address space to map. map_base : int Offset (in bytes) of the memory to be mapped. map_size : int Amount of memory to map (in bytes). access : False Unused parameter. suggested : Optional[int], optional If not None, the operating system attempts to map the memory to the address specified. There is no guarantee, however, that the memory will be mapped to that address. This operation may map the memory into an address region different from the suggested one. Returns ------- int Address in your process space where the memory was mapped constants.StatusCode Return value of the library call. """ if access is False: access = constants.VI_FALSE elif access != constants.VI_FALSE: warnings.warn("In enable_event, context will be set VI_NULL.") access = constants.VI_FALSE address = ViAddr() ret = library.viMapAddress( session, map_space, map_base, map_size, access, suggested, byref(address) ) return address, ret def map_trigger(library, session, trigger_source, trigger_destination, mode): """Map the specified trigger source line to the specified destination line. Corresponds to viMapTrigger function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. trigger_source : constants.InputTriggerLine Source line from which to map. trigger_destination : constants.OutputTriggerLine Destination line to which to map. mode : None, optional Always None for this version of the VISA specification. Returns ------- constants.StatusCode Return value of the library call. """ return library.viMapTrigger(session, trigger_source, trigger_destination, mode) def memory_allocation(library, session, size, extended=False): """Allocate memory from a resource's memory region. Corresponds to viMemAlloc* functions of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. size : int Specifies the size of the allocation. extended : bool, optional Use 64 bits offset independent of the platform. Returns ------- int offset of the allocated memory constants.StatusCode Return value of the library call. """ offset = ViBusAddress() if extended: ret = library.viMemAllocEx(session, size, byref(offset)) else: ret = library.viMemAlloc(session, size, byref(offset)) return offset, ret def memory_free(library, session, offset, extended=False): """Frees memory previously allocated using the memory_allocation() operation. Corresponds to viMemFree* function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. offset : int Offset of the memory to free. extended : bool, optional Use 64 bits offset independent of the platform. Returns ------- constants.StatusCode Return value of the library call. """ if extended: return library.viMemFreeEx(session, offset) else: return library.viMemFree(session, offset) def move( library, session, source_space, source_offset, source_width, destination_space, destination_offset, destination_width, length, ): """Moves a block of data. Corresponds to viMove function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. source_space : constants.AddressSpace Specifies the address space of the source. source_offset : int Offset of the starting address or register from which to read. source_width : constants.DataWidth Specifies the data width of the source. destination_space : constants.AddressSpace Specifies the address space of the destination. destination_offset : int Offset of the starting address or register to which to write. destination_width : constants.DataWidth Specifies the data width of the destination. length: int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. Returns ------- constants.StatusCode Return value of the library call. """ return library.viMove( session, source_space, source_offset, source_width, destination_space, destination_offset, destination_width, length, ) def move_asynchronously( library, session, source_space, source_offset, source_width, destination_space, destination_offset, destination_width, length, ): """Moves a block of data asynchronously. Corresponds to viMoveAsync function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. source_space : constants.AddressSpace Specifies the address space of the source. source_offset : int Offset of the starting address or register from which to read. source_width : constants.DataWidth Specifies the data width of the source. destination_space : constants.AddressSpace Specifies the address space of the destination. destination_offset : int Offset of the starting address or register to which to write. destination_width : constants.DataWidth Specifies the data width of the destination. length : int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. Returns ------- VISAJobID Job identifier of this asynchronous move operation constants.StatusCode Return value of the library call. """ job_id = ViJobId() ret = library.viMoveAsync( session, source_space, source_offset, source_width, destination_space, destination_offset, destination_width, length, byref(job_id), ) return job_id, ret def move_in_8(library, session, space, offset, length, extended=False): """Moves an 8-bit block of data to local memory. Corresponds to viMoveIn8* functions of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space from which to move the data. offset : int Offset (in bytes) of the address or register from which to read. length : int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. extended : bool, optional Use 64 bits offset independent of the platform, by default False. Returns ------- data : List[int] Data read from the bus status_code : constants.StatusCode Return value of the library call. """ buffer_8 = (ViUInt8 * length)() if extended: ret = library.viMoveIn8Ex(session, space, offset, length, buffer_8) else: ret = library.viMoveIn8(session, space, offset, length, buffer_8) return list(buffer_8), ret def move_in_16(library, session, space, offset, length, extended=False): """Moves an 16-bit block of data to local memory. Corresponds to viMoveIn816 functions of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space from which to move the data. offset : int Offset (in bytes) of the address or register from which to read. length : int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. extended : bool, optional Use 64 bits offset independent of the platform, by default False. Returns ------- data : List[int] Data read from the bus status_code : constants.StatusCode Return value of the library call. """ buffer_16 = (ViUInt16 * length)() if extended: ret = library.viMoveIn16Ex(session, space, offset, length, buffer_16) else: ret = library.viMoveIn16(session, space, offset, length, buffer_16) return list(buffer_16), ret def move_in_32(library, session, space, offset, length, extended=False): """Moves an 32-bit block of data to local memory. Corresponds to viMoveIn32* functions of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space from which to move the data. offset : int Offset (in bytes) of the address or register from which to read. length : int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. extended : bool, optional Use 64 bits offset independent of the platform, by default False. Returns ------- data : List[int] Data read from the bus status_code : constants.StatusCode Return value of the library call. """ buffer_32 = (ViUInt32 * length)() if extended: ret = library.viMoveIn32Ex(session, space, offset, length, buffer_32) else: ret = library.viMoveIn32(session, space, offset, length, buffer_32) return list(buffer_32), ret def move_in_64(library, session, space, offset, length, extended=False): """Moves an 64-bit block of data to local memory. Corresponds to viMoveIn8* functions of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space from which to move the data. offset : int Offset (in bytes) of the address or register from which to read. length : int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. extended : bool, optional Use 64 bits offset independent of the platform, by default False. Returns ------- data : List[int] Data read from the bus status_code : constants.StatusCode Return value of the library call. """ buffer_64 = (ViUInt64 * length)() if extended: ret = library.viMoveIn64Ex(session, space, offset, length, buffer_64) else: ret = library.viMoveIn64(session, space, offset, length, buffer_64) return list(buffer_64), ret def move_out_8(library, session, space, offset, length, data, extended=False): """Moves an 8-bit block of data from local memory. Corresponds to viMoveOut8* functions of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space into which move the data. offset : int Offset (in bytes) of the address or register from which to read. length : int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. data : Iterable[int] Data to write to bus. extended : bool, optional Use 64 bits offset independent of the platform, by default False. Returns ------- constants.StatusCode Return value of the library call. """ converted_buffer = (ViUInt8 * length)(*tuple(data)) if extended: return library.viMoveOut8Ex(session, space, offset, length, converted_buffer) else: return library.viMoveOut8(session, space, offset, length, converted_buffer) def move_out_16(library, session, space, offset, length, data, extended=False): """Moves an 16-bit block of data from local memory. Corresponds to viMoveOut16* functions of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space into which move the data. offset : int Offset (in bytes) of the address or register from which to read. length : int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. data : Iterable[int] Data to write to bus. extended : bool, optional Use 64 bits offset independent of the platform, by default False. Returns ------- constants.StatusCode Return value of the library call. """ converted_buffer = (ViUInt16 * length)(*tuple(data)) if extended: return library.viMoveOut16Ex(session, space, offset, length, converted_buffer) else: return library.viMoveOut16(session, space, offset, length, converted_buffer) def move_out_32(library, session, space, offset, length, data, extended=False): """Moves an 32-bit block of data from local memory. Corresponds to viMoveOut32* functions of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space into which move the data. offset : int Offset (in bytes) of the address or register from which to read. length : int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. data : Iterable[int] Data to write to bus. extended : bool, optional Use 64 bits offset independent of the platform, by default False. Returns ------- constants.StatusCode Return value of the library call. """ converted_buffer = (ViUInt32 * length)(*tuple(data)) if extended: return library.viMoveOut32Ex(session, space, offset, length, converted_buffer) else: return library.viMoveOut32(session, space, offset, length, converted_buffer) def move_out_64(library, session, space, offset, length, data, extended=False): """Moves an 64-bit block of data from local memory. Corresponds to viMoveOut64* functions of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space into which move the data. offset : int Offset (in bytes) of the address or register from which to read. length : int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. data : Iterable[int] Data to write to bus. extended : bool, optional Use 64 bits offset independent of the platform, by default False. Returns ------- constants.StatusCode Return value of the library call. """ converted_buffer = (ViUInt64 * length)(*tuple(data)) if extended: return library.viMoveOut64Ex(session, space, offset, length, converted_buffer) else: return library.viMoveOut64(session, space, offset, length, converted_buffer) # noinspection PyShadowingBuiltins def open( library, session, resource_name, access_mode=constants.AccessModes.no_lock, open_timeout=constants.VI_TMO_IMMEDIATE, ): """Opens a session to the specified resource. Corresponds to viOpen function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISARMSession Resource Manager session (should always be a session returned from open_default_resource_manager()). resource_name : str Unique symbolic name of a resource. access_mode : constants.AccessModes, optional Specifies the mode by which the resource is to be accessed. open_timeout : int If the ``access_mode`` parameter requests a lock, then this parameter specifies the absolute time period (in milliseconds) that the resource waits to get unlocked before this operation returns an error. Returns ------- VISASession Unique logical identifier reference to a session constants.StatusCode Return value of the library call. """ try: open_timeout = int(open_timeout) except ValueError: raise ValueError( "open_timeout (%r) must be an integer (or compatible type)" % open_timeout ) out_session = ViSession() # [ViSession, ViRsrc, ViAccessMode, ViUInt32, ViPSession] # ViRsrc converts from (str, unicode, bytes) to bytes ret = library.viOpen( session, resource_name, access_mode, open_timeout, byref(out_session) ) return out_session.value, ret def open_default_resource_manager(library): """This function returns a session to the Default Resource Manager resource. Corresponds to viOpenDefaultRM function of the VISA library. Returns ------- VISARMSession Unique logical identifier to a Default Resource Manager session constants.StatusCode Return value of the library call. """ session = ViSession() ret = library.viOpenDefaultRM(byref(session)) return session.value, ret def out_8(library, session, space, offset, data, extended=False): """Write an 8-bit value to the specified memory space and offset. Corresponds to viOut8* functions of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space into which to write. offset : int Offset (in bytes) of the address or register from which to read. data : int Data to write to bus. extended : bool, optional Use 64 bits offset independent of the platform. Returns ------- constants.StatusCode Return value of the library call. """ if extended: return library.viOut8Ex(session, space, offset, data) else: return library.viOut8(session, space, offset, data) def out_16(library, session, space, offset, data, extended=False): """Write a 16-bit value to the specified memory space and offset. Corresponds to viOut16* functions of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space into which to write. offset : int Offset (in bytes) of the address or register from which to read. data : int Data to write to bus. extended : bool, optional Use 64 bits offset independent of the platform. Returns ------- constants.StatusCode Return value of the library call. """ if extended: return library.viOut16Ex(session, space, offset, data, extended=False) else: return library.viOut16(session, space, offset, data, extended=False) def out_32(library, session, space, offset, data, extended=False): """Write a 32-bit value to the specified memory space and offset. Corresponds to viOut32* functions of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space into which to write. offset : int Offset (in bytes) of the address or register from which to read. data : int Data to write to bus. extended : bool, optional Use 64 bits offset independent of the platform. Returns ------- constants.StatusCode Return value of the library call. """ if extended: return library.viOut32Ex(session, space, offset, data) else: return library.viOut32(session, space, offset, data) def out_64(library, session, space, offset, data, extended=False): """Write a 64-bit value to the specified memory space and offset. Corresponds to viOut64* functions of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space into which to write. offset : int Offset (in bytes) of the address or register from which to read. data : int Data to write to bus. extended : bool, optional Use 64 bits offset independent of the platform. Returns ------- constants.StatusCode Return value of the library call. """ if extended: return library.viOut64Ex(session, space, offset, data) else: return library.viOut64(session, space, offset, data) def parse_resource(library, session, resource_name): """Parse a resource string to get the interface information. Corresponds to viParseRsrc function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISARMSession Resource Manager session (should always be the Default Resource Manager for VISA returned from open_default_resource_manager()). resource_name : str Unique symbolic name of a resource. Returns ------- ResourceInfo Resource information with interface type and board number constants.StatusCode Return value of the library call. """ interface_type = ViUInt16() interface_board_number = ViUInt16() # [ViSession, ViRsrc, ViPUInt16, ViPUInt16] # ViRsrc converts from (str, unicode, bytes) to bytes ret = library.viParseRsrc( session, resource_name, byref(interface_type), byref(interface_board_number) ) return ( ResourceInfo( constants.InterfaceType(interface_type.value), interface_board_number.value, None, None, None, ), ret, ) def parse_resource_extended(library, session, resource_name): """Parse a resource string to get extended interface information. Corresponds to viParseRsrcEx function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISARMSession Resource Manager session (should always be the Default Resource Manager for VISA returned from open_default_resource_manager()). resource_name : str Unique symbolic name of a resource. Returns ------- ResourceInfo Resource information with interface type and board number constants.StatusCode Return value of the library call. """ interface_type = ViUInt16() interface_board_number = ViUInt16() resource_class = create_string_buffer(constants.VI_FIND_BUFLEN) unaliased_expanded_resource_name = create_string_buffer(constants.VI_FIND_BUFLEN) alias_if_exists = create_string_buffer(constants.VI_FIND_BUFLEN) # [ViSession, ViRsrc, ViPUInt16, ViPUInt16, ViAChar, ViAChar, ViAChar] # ViRsrc converts from (str, unicode, bytes) to bytes ret = library.viParseRsrcEx( session, resource_name, byref(interface_type), byref(interface_board_number), resource_class, unaliased_expanded_resource_name, alias_if_exists, ) res = [ buffer_to_text(val) for val in (resource_class, unaliased_expanded_resource_name, alias_if_exists) ] if res[-1] == "": res[-1] = None return ( ResourceInfo( constants.InterfaceType(interface_type.value), interface_board_number.value, *res ), ret, ) def peek_8(library, session, address): """Read an 8-bit value from the specified address. Corresponds to viPeek8 function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. address : VISAMemoryAddress Source address to read the value. Returns ------- int Data read from bus constants.StatusCode Return value of the library call. """ value_8 = ViUInt8() ret = library.viPeek8(session, address, byref(value_8)) return value_8.value, ret def peek_16(library, session, address): """Read an 16-bit value from the specified address. Corresponds to viPeek16 function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. address : VISAMemoryAddress Source address to read the value. Returns ------- int Data read from bus constants.StatusCode Return value of the library call. """ value_16 = ViUInt16() ret = library.viPeek16(session, address, byref(value_16)) return value_16.value, ret def peek_32(library, session, address): """Read an 32-bit value from the specified address. Corresponds to viPeek32 function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. address : VISAMemoryAddress Source address to read the value. Returns ------- int Data read from bus constants.StatusCode Return value of the library call. """ value_32 = ViUInt32() ret = library.viPeek32(session, address, byref(value_32)) return value_32.value, ret def peek_64(library, session, address): """Read an 64-bit value from the specified address. Corresponds to viPeek64 function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. address : VISAMemoryAddress Source address to read the value. Returns ------- int Data read from bus constants.StatusCode Return value of the library call. """ value_64 = ViUInt64() ret = library.viPeek64(session, address, byref(value_64)) return value_64.value, ret def poke_8(library, session, address, data): """Write an 8-bit value to the specified address. Corresponds to viPoke8 function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. address : VISAMemoryAddress Source address to read the value. data : int Data to write. Returns ------- constants.StatusCode Return value of the library call. """ return library.viPoke8(session, address, data) def poke_16(library, session, address, data): """Write an 16-bit value to the specified address. Corresponds to viPoke16 function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. address : VISAMemoryAddress Source address to read the value. data : int Data to write. Returns ------- constants.StatusCode Return value of the library call. """ return library.viPoke16(session, address, data) def poke_32(library, session, address, data): """Write an 32-bit value to the specified address. Corresponds to viPoke32 function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. address : VISAMemoryAddress Source address to read the value. data : int Data to write. Returns ------- constants.StatusCode Return value of the library call. """ return library.viPoke32(session, address, data) def poke_64(library, session, address, data): """Write an 64-bit value to the specified address. Corresponds to viPoke64 function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. address : VISAMemoryAddress Source address to read the value. data : int Data to write. Returns ------- constants.StatusCode Return value of the library call. """ return library.viPoke64(session, address, data) def read(library, session, count): """Reads data from device or interface synchronously. Corresponds to viRead function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. count : int Number of bytes to be read. Returns ------- bytes Date read constants.StatusCode Return value of the library call. """ buffer = create_string_buffer(count) return_count = ViUInt32() ret = library.viRead(session, buffer, count, byref(return_count)) return buffer.raw[: return_count.value], ret def read_stb(library, session): """Reads a status byte of the service request. Corresponds to viReadSTB function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. Returns ------- int Service request status byte constants.StatusCode Return value of the library call. """ status = ViUInt16() ret = library.viReadSTB(session, byref(status)) return status.value, ret def read_to_file(library, session, filename, count): """Read data synchronously, and store the transferred data in a file. Corresponds to viReadToFile function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. filename : str Name of file to which data will be written. count : int Number of bytes to be read. Returns ------- int Number of bytes actually transferred constants.StatusCode Return value of the library call. """ return_count = ViUInt32() ret = library.viReadToFile(session, filename, count, return_count) return return_count, ret def set_attribute(library, session, attribute, attribute_state): """Set the state of an attribute. Corresponds to viSetAttribute function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. attribute : constants.ResourceAttribute Attribute for which the state is to be modified. attribute_state : Any The state of the attribute to be set for the specified object. Returns ------- constants.StatusCode Return value of the library call. """ return library.viSetAttribute(session, attribute, attribute_state) def set_buffer(library, session, mask, size): """Set the size for the formatted I/O and/or low-level I/O communication buffer(s). Corresponds to viSetBuf function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. mask : constants.BufferType Specifies the type of buffer. size : int The size to be set for the specified buffer(s). Returns ------- constants.StatusCode Return value of the library call. """ return library.viSetBuf(session, mask, size) def status_description(library, session, status): """Return a user-readable description of the status code passed to the operation. Corresponds to viStatusDesc function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. status : constants.StatusCode Status code to interpret. Returns ------- str User-readable string interpretation of the status code. constants.StatusCode Return value of the library call. """ description = create_string_buffer(256) ret = library.viStatusDesc(session, status, description) return buffer_to_text(description), ret def terminate(library, session, degree, job_id): """Request a VISA session to terminate normal execution of an operation. Corresponds to viTerminate function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. degree : None Not used in this version of the VISA specification. job_id : VISAJobId Specifies an operation identifier. If a user passes None as the job_id value to viTerminate(), a VISA implementation should abort any calls in the current process executing on the specified vi. Any call that is terminated this way should return VI_ERROR_ABORT. Returns ------- constants.StatusCode Return value of the library call. """ return library.viTerminate(session, degree, job_id) def uninstall_handler(library, session, event_type, handler, user_handle=None): """Uninstall handlers for events. Corresponds to viUninstallHandler function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. event_type : constants.EventType Logical event identifier. handler : VISAHandler Handler to be uninstalled by a client application. user_handle: A value specified by an application that can be used for identifying handlers uniquely in a session for an event. The modified value of the user_handle as returned by install_handler should be used instead of the original value. Returns ------- constants.StatusCode Return value of the library call. """ with set_user_handle_type(library, user_handle): if user_handle is not None: user_handle = byref(user_handle) return library.viUninstallHandler(session, event_type, handler, user_handle) def unlock(library, session): """Relinquish a lock for the specified resource. Corresponds to viUnlock function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. Returns ------- constants.StatusCode Return value of the library call. """ return library.viUnlock(session) def unmap_address(library, session): """Unmap memory space previously mapped by map_address(). Corresponds to viUnmapAddress function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. Returns ------- constants.StatusCode Return value of the library call. """ return library.viUnmapAddress(session) def unmap_trigger(library, session, trigger_source, trigger_destination): """Undo a previous map between a trigger source line and a destination line. Corresponds to viUnmapTrigger function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. trigger_source : constants.InputTriggerLine Source line used in previous map. trigger_destination : constants.OutputTriggerLine Destination line used in previous map. Returns ------- constants.StatusCode Return value of the library call. """ return library.viUnmapTrigger(session, trigger_source, trigger_destination) def usb_control_in( library, session, request_type_bitmap_field, request_id, request_value, index, length=0, ): """Perform a USB control pipe transfer from the device. Corresponds to viUsbControlIn function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. request_type_bitmap_field : int bmRequestType parameter of the setup stage of a USB control transfer. request_id : int bRequest parameter of the setup stage of a USB control transfer. request_value : int wValue parameter of the setup stage of a USB control transfer. index : int wIndex parameter of the setup stage of a USB control transfer. This is usually the index of the interface or endpoint. length : int, optional wLength parameter of the setup stage of a USB control transfer. This value also specifies the size of the data buffer to receive the data from the optional data stage of the control transfer. Returns ------- bytes The data buffer that receives the data from the optional data stage of the control transfer constants.StatusCode Return value of the library call. """ buffer = create_string_buffer(length) return_count = ViUInt16() ret = library.viUsbControlIn( session, request_type_bitmap_field, request_id, request_value, index, length, buffer, byref(return_count), ) return buffer.raw[: return_count.value], ret def usb_control_out( library, session, request_type_bitmap_field, request_id, request_value, index, data="", ): """Perform a USB control pipe transfer to the device. Corresponds to viUsbControlOut function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. request_type_bitmap_field : int bmRequestType parameter of the setup stage of a USB control transfer. request_id : int bRequest parameter of the setup stage of a USB control transfer. request_value : int wValue parameter of the setup stage of a USB control transfer. index : int wIndex parameter of the setup stage of a USB control transfer. This is usually the index of the interface or endpoint. data : bytes, optional The data buffer that sends the data in the optional data stage of the control transfer. Returns ------- constants.StatusCode Return value of the library call. """ length = len(data) return library.viUsbControlOut( session, request_type_bitmap_field, request_id, request_value, index, length, data, ) def vxi_command_query(library, session, mode, command): """Send the device a miscellaneous command or query and/or retrieves the response to a previous query. Corresponds to viVxiCommandQuery function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. mode : constants.VXICommands Specifies whether to issue a command and/or retrieve a response. command : int The miscellaneous command to send. Returns ------- int The response retrieved from the device constants.StatusCode Return value of the library call. """ response = ViUInt32() ret = library.viVxiCommandQuery(session, mode, command, byref(response)) return response.value, ret def wait_on_event(library, session, in_event_type, timeout): """Wait for an occurrence of the specified event for a given session. Corresponds to viWaitOnEvent function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. in_event_type : constants.EventType Logical identifier of the event(s) to wait for. timeout : int Absolute time period in time units that the resource shall wait for a specified event to occur before returning the time elapsed error. The time unit is in milliseconds. Returns ------- constants.EventType Logical identifier of the event actually received VISAEventContext A handle specifying the unique occurrence of an event constants.StatusCode Return value of the library call. """ out_event_type = ViEventType() out_context = ViEvent() ret = library.viWaitOnEvent( session, in_event_type, timeout, byref(out_event_type), byref(out_context) ) return out_event_type.value, out_context, ret def write(library, session, data): """Write data to device or interface synchronously. Corresponds to viWrite function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. data : bytes Data to be written. Returns ------- int Number of bytes actually transferred constants.StatusCode Return value of the library call. """ return_count = ViUInt32() # [ViSession, ViBuf, ViUInt32, ViPUInt32] ret = library.viWrite(session, data, len(data), byref(return_count)) return return_count.value, ret def write_asynchronously(library, session, data): """Write data to device or interface asynchronously. Corresponds to viWriteAsync function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. data : bytes Data to be written. Returns ------- VISAJobID Job ID of this asynchronous write operation constants.StatusCode Return value of the library call. """ job_id = ViJobId() # [ViSession, ViBuf, ViUInt32, ViPJobId] ret = library.viWriteAsync(session, data, len(data), byref(job_id)) return job_id, ret def write_from_file(library, session, filename, count): """Take data from a file and write it out synchronously. Corresponds to viWriteFromFile function of the VISA library. Parameters ---------- library : ctypes.WinDLL or ctypes.CDLL ctypes wrapped library. session : VISASession Unique logical identifier to a session. filename : str Name of file from which data will be read. count : int Number of bytes to be written. Returns ------- int Number of bytes actually transferred constants.StatusCode Return value of the library call. """ return_count = ViUInt32() ret = library.viWriteFromFile(session, filename, count, return_count) return return_count, ret pyvisa-1.11.3/pyvisa/ctwrapper/highlevel.py000066400000000000000000000325311375165327600207760ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Highlevel wrapper of the VISA Library. This file is part of PyVISA. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ import ctypes import logging import warnings from collections import OrderedDict from typing import ( Any, Callable, Dict, List, Optional, SupportsBytes, Tuple, Type, TypeVar, Union, ) from pyvisa import constants, errors, highlevel, logger, typing from ..util import LibraryPath, add_user_dll_extra_paths, read_user_library_path from . import functions, types from .cthelper import Library, find_library logger = logging.LoggerAdapter(logger, {"backend": "ivi"}) # type: ignore T = TypeVar("T", bound=highlevel.VisaLibraryBase) def add_visa_methods(aclass: Type[T]) -> Type[T]: """Add the methods to the library.""" for method in functions.visa_functions: setattr(aclass, method, getattr(functions, method)) return aclass def _args_to_str(args: Tuple[Any, ...]) -> Tuple[str, ...]: """Convert function arguments to str.""" out = [] for arg in args: try: out.append(str(arg._obj)) except AttributeError: out.append(arg) return tuple(out) def unique(seq): """Keep unique while preserving order.""" seen = set() return [x for x in seq if not (x in seen or seen.add(x))] @add_visa_methods class IVIVisaLibrary(highlevel.VisaLibraryBase): """High level IVI-VISA Library wrapper using ctypes. The easiest way to instantiate the library is to let `pyvisa` find the right one for you. This looks first in your configuration file (~/.pyvisarc). If it fails, it uses `ctypes.util.find_library` to try to locate a library in a way similar to what the compiler does: >>> visa_library = IVIVisaLibrary() But you can also specify the path: >>> visa_library = IVIVisaLibrary('/my/path/visa.so') """ @staticmethod def get_library_paths() -> Tuple[LibraryPath, ...]: """Return a tuple of possible library paths.""" # Add extra .dll dependency search paths before attempting to load libraries add_user_dll_extra_paths() # Try to find IVI libraries using known names. tmp: List[str] tmp = [ find_library(library_path) for library_path in ("visa", "visa32", "visa32.dll", "visa64", "visa64.dll") ] logger.debug("Automatically found library files: %s" % tmp) # Prepend the path provided by the user in configuration files (if any). user_lib = read_user_library_path() if user_lib: tmp.insert(0, user_lib) # Deduplicate and convert string paths to LibraryPath objects return tuple( LibraryPath(library_path) for library_path in unique(tmp) if library_path is not None ) @classmethod def get_debug_info(cls) -> Dict[str, Union[str, Dict[str, Any]]]: """Return a list of lines with backend info.""" from pyvisa import __version__ d: Dict[str, Union[str, Dict[str, Any]]] = OrderedDict() d["Version"] = "%s (bundled with PyVISA)" % __version__ paths = cls.get_library_paths() 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 try: lib = cls(visalib) sess, _ = lib.open_default_resource_manager() nfo["Vendor"] = str( lib.get_attribute( sess, constants.ResourceAttribute.resource_manufacturer_name )[0] ) nfo["Impl. Version"] = str( lib.get_attribute( sess, constants.ResourceAttribute.resource_manufacturer_name )[0] ) nfo["Spec. Version"] = str( lib.get_attribute( sess, constants.ResourceAttribute.resource_manufacturer_name )[0] ) lib.close(sess) except Exception as e: err_string = str(e) if "No matching architecture" in err_string: nfo[ "Could not get more info" ] = "Interpreter and library have different bitness." else: nfo["Could not get more info"] = err_string.split("\n") d["#%d: %s" % (ndx, visalib)] = nfo if not paths: d["Binary library"] = "Not found" return d def _init(self) -> None: try: lib = Library(self.library_path) except OSError as exc: raise errors.LibraryError.from_exception(exc, self.library_path) self.lib = lib self._async_read_jobs: List[Tuple[types.ViJobId, SupportsBytes]] = [] # Set the argtypes, restype and errcheck for each function # of the visa library. Additionally store in `_functions` the # name of the functions. functions.set_signatures(self.lib, errcheck=self._return_handler) logger.debug( "Library signatures: %d ok, %d failed", len(getattr(self.lib, "_functions", [])), len(getattr(self.lib, "_functions_failed", [])), ) # Set the library functions as attributes of the object. for method_name in getattr(self.lib, "_functions", []): setattr(self, method_name, getattr(self.lib, method_name)) def _return_handler(self, ret_value: int, func: Callable, arguments: tuple) -> Any: """Check return values for errors and warnings.""" logger.debug( "%s%s -> %r", func.__name__, _args_to_str(arguments), ret_value, extra=self._logging_extra, ) # The first argument of almost all registered visa functions is a session. # We store the error code per session session = None if func.__name__ not in ("viFindNext",): try: session = arguments[0] except KeyError: raise Exception( "Function %r does not seem to be a valid " "visa function (len args %d)" % (func, len(arguments)) ) # Functions that use the first parameter to get a session value. if func.__name__ in ("viOpenDefaultRM",): session = session._obj.value if not isinstance(session, int): # Functions that might or might not have a session in the first argument. if func.__name__ not in ( "viClose", "viGetAttribute", "viSetAttribute", "viStatusDesc", ): raise Exception( "Function %r does not seem to be a valid " "visa function (type args[0] %r)" % (func, type(session)) ) # Set session back to a safe value session = None return self.handle_return_value(session, ret_value) # type: ignore def list_resources( self, session: typing.VISARMSession, query: str = "?*::INSTR" ) -> Tuple[str, ...]: r"""Returns a tuple of all connected devices matching query. Parameters ---------- session : typing.VISARMSession Unused, present for consistency query : str Query using the VISA Resource Regular Expression syntax - which is not the same as the Python regular expression syntax. (see below) Notes ----- The VISA Resource Regular Expression syntax is defined in the VISA Library specification: http://www.ivifoundation.org/docs/vpp43.pdf Symbol Meaning ---------- ---------- ? Matches any one character. \ Makes the character that follows it an ordinary character instead of special character. For example, when a question mark follows a backslash (\?), it matches the ? character instead of any one character. [list] Matches any one character from the enclosed list. You can use a hyphen to match a range of characters. [^list] Matches any character not in the enclosed list. You can use a hyphen to match a range of characters. * Matches 0 or more occurrences of the preceding character or expression. + Matches 1 or more occurrences of the preceding character or expression. Exp|exp Matches either the preceding or following expression. The or operator | matches the entire expression that precedes or follows it and not just the character that precedes or follows it. For example, VXI|GPIB means (VXI)|(GPIB), not VX(I|G)PIB. (exp) Grouping characters or expressions. Thus the default query, '?*::INSTR', matches any sequences of characters ending ending with '::INSTR'. """ resources: List[str] = [] # Ignore some type checks because method are dynamically set try: ( find_list, return_counter, instrument_description, err, ) = self._find_resources( # type: ignore session, query ) except errors.VisaIOError as e: if e.error_code == constants.StatusCode.error_resource_not_found: return tuple() raise e try: resources.append(instrument_description) for i in range(return_counter - 1): resources.append(self._find_next(find_list)[0]) # type: ignore finally: # This is the only occurrence of a find list so ignore the typing error # since it would make things harder to follow to document ViFindList as # supported. self.close(find_list) # type: ignore return tuple(resource for resource in resources) def read_asynchronously( self, session: typing.VISASession, count: int ) -> Tuple[SupportsBytes, types.ViJobId, constants.StatusCode]: """Read data from device or interface asynchronously. Corresponds to viReadAsync function of the VISA library. Since the asynchronous operation may complete before the function call return implementation should make sure that get_buffer_from_id will be able to return the proper buffer before this method returns. Parameters ---------- session : typing.VISASession Unique logical identifier to a session. count : int Number of bytes to be read. Returns ------- SupportsBytes Buffer in which the data will be written. types.ViJobId Id of the job. constants.StatusCode Return value of the library call. """ # The buffer actually supports bytes but typing fails buffer = ctypes.create_string_buffer(count) job_id = types.ViJobId() self._async_read_jobs.append((job_id, buffer)) # type: ignore ret = self.lib.viReadAsync(session, buffer, count, ctypes.byref(job_id)) return buffer, job_id.value, ret # type: ignore def get_buffer_from_id(self, job_id: typing.VISAJobID) -> Optional[SupportsBytes]: """Retrieve the buffer associated with a job id created in read_asynchronously. Parameters ---------- job_id : VISAJobID Id of the job for which to retrieve the buffer. Returns ------- SupportsBytes Buffer in which the data are stored. """ for jid, buffer in self._async_read_jobs: if job_id == jid.value: return buffer return None class NIVisaLibrary(IVIVisaLibrary): # pragma: no cover """Deprecated name for IVIVisaLibrary. This class will be removed in 1.12 """ @staticmethod def get_library_paths() -> Tuple[LibraryPath, ...]: """Return a tuple of possible library paths.""" warnings.warn( "NIVisaLibrary is deprecated and will be removed in 1.12. " "Use IVIVisaLibrary instead.", FutureWarning, ) return IVIVisaLibrary.get_library_paths() @classmethod def get_debug_info(cls) -> Dict[str, Union[str, Dict[str, Any]]]: """Return a list of lines with backend info.""" warnings.warn( "NIVisaLibrary is deprecated and will be removed in 1.12. " "Use IVIVisaLibrary instead.", FutureWarning, ) return IVIVisaLibrary.get_debug_info() def __new__( # type: ignore cls: Type["NIVisaLibrary"], library_path: str = "" ) -> highlevel.VisaLibraryBase: warnings.warn( "NIVisaLibrary is deprecated and will be removed in 1.12. " "Use IVIVisaLibrary instead.", FutureWarning, ) return IVIVisaLibrary.__new__(cls, library_path) pyvisa-1.11.3/pyvisa/ctwrapper/types.py000066400000000000000000000076461375165327600202040ustar00rootroot00000000000000# -*- coding: utf-8 -*- """VISA VPP-4.3 data types (VPP-4.3.2 spec, section 3) using ctypes constants. This file is part of PyVISA. All data types that are defined by VPP-4.3.2. The module exports all data types including the pointer and array types. This means "ViUInt32" and such. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ import ctypes as _ctypes from .cthelper import FUNCTYPE # Part One: Type Assignments for VISA and Instrument Drivers, see spec table # 3.1.1. # # Remark: The pointer and probably also the array variants are of no # significance in Python because there is no native call-by-reference. # However, as long as I'm not fully sure about this, they won't hurt. def _type_pair(ctypes_type): return ctypes_type, _ctypes.POINTER(ctypes_type) def _type_triplet(ctypes_type): return _type_pair(ctypes_type) + (_ctypes.POINTER(ctypes_type),) ViUInt64, ViPUInt64, ViAUInt64 = _type_triplet(_ctypes.c_uint64) ViInt64, ViPInt64, ViAInt64 = _type_triplet(_ctypes.c_int64) ViUInt32, ViPUInt32, ViAUInt32 = _type_triplet(_ctypes.c_uint32) ViInt32, ViPInt32, ViAInt32 = _type_triplet(_ctypes.c_int32) ViUInt16, ViPUInt16, ViAUInt16 = _type_triplet(_ctypes.c_ushort) ViInt16, ViPInt16, ViAInt16 = _type_triplet(_ctypes.c_short) ViUInt8, ViPUInt8, ViAUInt8 = _type_triplet(_ctypes.c_ubyte) ViInt8, ViPInt8, ViAInt8 = _type_triplet(_ctypes.c_byte) ViAddr, ViPAddr, ViAAddr = _type_triplet(_ctypes.c_void_p) ViChar, ViPChar, ViAChar = _type_triplet(_ctypes.c_char) ViByte, ViPByte, ViAByte = _type_triplet(_ctypes.c_ubyte) ViBoolean, ViPBoolean, ViABoolean = _type_triplet(ViUInt16) ViReal32, ViPReal32, ViAReal32 = _type_triplet(_ctypes.c_float) ViReal64, ViPReal64, ViAReal64 = _type_triplet(_ctypes.c_double) class ViString(object): @classmethod def from_param(cls, obj): if isinstance(obj, str): return bytes(obj, "ascii") return obj class ViAString(object): @classmethod def from_param(cls, obj): return _ctypes.POINTER(obj) ViPString = ViString # This follows visa.h definition, but involves a lot of manual conversion. # ViBuf, ViPBuf, ViABuf = ViPByte, ViPByte, _ctypes.POINTER(ViPByte) ViBuf, ViPBuf, ViABuf = ViPString, ViPString, ViAString def buffer_to_text(buf) -> str: return buf.value.decode("ascii") ViRsrc = ViString ViPRsrc = ViString ViARsrc = ViAString ViKeyId, ViPKeyId = ViString, ViPString ViStatus, ViPStatus, ViAStatus = _type_triplet(ViInt32) ViVersion, ViPVersion, ViAVersion = _type_triplet(ViUInt32) _ViObject, ViPObject, ViAObject = _type_triplet(ViUInt32) _ViSession, ViPSession, ViASession = _type_triplet(ViUInt32) class ViObject(_ViObject): # type: ignore @classmethod def from_param(cls, obj): if obj is None: raise ValueError("Session cannot be None. The resource might be closed.") return _ViObject.from_param(obj) ViSession = ViObject ViAttr = ViUInt32 ViConstString = _ctypes.POINTER(ViChar) # Part Two: Type Assignments for VISA only, see spec table 3.1.2. The # difference to the above is of no significance in Python, so I use it here # only for easier synchronisation with the spec. ViAccessMode, ViPAccessMode = _type_pair(ViUInt32) ViBusAddress, ViPBusAddress = _type_pair(ViUInt32) ViBusAddress64, ViPBusAddress64 = _type_pair(ViUInt64) ViBusSize = ViUInt32 ViAttrState, ViPAttrState = _type_pair(ViUInt32) # The following is weird, taken from news:zn2ek2w2.fsf@python.net ViVAList = _ctypes.POINTER(_ctypes.c_char) ViEventType, ViPEventType, ViAEventType = _type_triplet(ViUInt32) ViPAttr = _ctypes.POINTER(ViAttr) ViAAttr = ViPAttr ViEventFilter = ViUInt32 ViFindList, ViPFindList = _type_pair(ViObject) ViEvent, ViPEvent = _type_pair(ViObject) ViJobId, ViPJobId = _type_pair(ViUInt32) # Class of callback functions for event handling, first type is result type ViHndlr = FUNCTYPE(ViStatus, ViSession, ViEventType, ViEvent, ViAddr) pyvisa-1.11.3/pyvisa/errors.py000066400000000000000000000631151375165327600163360ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Exceptions hierarchy and textual explanations of VISA completion and error codes. This file is part of PyVISA. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ import warnings from typing import Any, Tuple from . import typing, util from .constants import ( VI_ERROR_ABORT, VI_ERROR_ALLOC, VI_ERROR_ASRL_FRAMING, VI_ERROR_ASRL_OVERRUN, VI_ERROR_ASRL_PARITY, VI_ERROR_ATTR_READONLY, VI_ERROR_BERR, VI_ERROR_CLOSING_FAILED, VI_ERROR_CONN_LOST, VI_ERROR_FILE_ACCESS, VI_ERROR_FILE_IO, VI_ERROR_HNDLR_NINSTALLED, VI_ERROR_IN_PROGRESS, VI_ERROR_INP_PROT_VIOL, VI_ERROR_INTF_NUM_NCONFIG, VI_ERROR_INTR_PENDING, VI_ERROR_INV_ACC_MODE, VI_ERROR_INV_ACCESS_KEY, VI_ERROR_INV_CONTEXT, VI_ERROR_INV_DEGREE, VI_ERROR_INV_EVENT, VI_ERROR_INV_EXPR, VI_ERROR_INV_FMT, VI_ERROR_INV_HNDLR_REF, VI_ERROR_INV_JOB_ID, VI_ERROR_INV_LENGTH, VI_ERROR_INV_LINE, VI_ERROR_INV_LOCK_TYPE, VI_ERROR_INV_MASK, VI_ERROR_INV_MECH, VI_ERROR_INV_MODE, VI_ERROR_INV_OBJECT, VI_ERROR_INV_OFFSET, VI_ERROR_INV_PARAMETER, VI_ERROR_INV_PROT, VI_ERROR_INV_RSRC_NAME, VI_ERROR_INV_SETUP, VI_ERROR_INV_SIZE, VI_ERROR_INV_SPACE, VI_ERROR_INV_WIDTH, VI_ERROR_IO, VI_ERROR_LIBRARY_NFOUND, VI_ERROR_LINE_IN_USE, VI_ERROR_MACHINE_NAVAIL, VI_ERROR_MEM_NSHARED, VI_ERROR_NCIC, VI_ERROR_NENABLED, VI_ERROR_NIMPL_OPER, VI_ERROR_NLISTENERS, VI_ERROR_NPERMISSION, VI_ERROR_NSUP_ALIGN_OFFSET, VI_ERROR_NSUP_ATTR, VI_ERROR_NSUP_ATTR_STATE, VI_ERROR_NSUP_FMT, VI_ERROR_NSUP_INTR, VI_ERROR_NSUP_LINE, VI_ERROR_NSUP_MECH, VI_ERROR_NSUP_MODE, VI_ERROR_NSUP_OFFSET, VI_ERROR_NSUP_OPER, VI_ERROR_NSUP_VAR_WIDTH, VI_ERROR_NSUP_WIDTH, VI_ERROR_NSYS_CNTLR, VI_ERROR_OUTP_PROT_VIOL, VI_ERROR_QUEUE_ERROR, VI_ERROR_QUEUE_OVERFLOW, VI_ERROR_RAW_RD_PROT_VIOL, VI_ERROR_RAW_WR_PROT_VIOL, VI_ERROR_RESP_PENDING, VI_ERROR_RSRC_BUSY, VI_ERROR_RSRC_LOCKED, VI_ERROR_RSRC_NFOUND, VI_ERROR_SESN_NLOCKED, VI_ERROR_SRQ_NOCCURRED, VI_ERROR_SYSTEM_ERROR, VI_ERROR_TMO, VI_ERROR_TRIG_NMAPPED, VI_ERROR_USER_BUF, VI_ERROR_WINDOW_MAPPED, VI_ERROR_WINDOW_NMAPPED, VI_SUCCESS, VI_SUCCESS_DEV_NPRESENT, VI_SUCCESS_EVENT_DIS, VI_SUCCESS_EVENT_EN, VI_SUCCESS_MAX_CNT, VI_SUCCESS_NCHAIN, VI_SUCCESS_NESTED_EXCLUSIVE, VI_SUCCESS_NESTED_SHARED, VI_SUCCESS_QUEUE_EMPTY, VI_SUCCESS_QUEUE_NEMPTY, VI_SUCCESS_SYNC, VI_SUCCESS_TERM_CHAR, VI_SUCCESS_TRIG_MAPPED, VI_WARN_CONFIG_NLOADED, VI_WARN_EXT_FUNC_NIMPL, VI_WARN_NSUP_ATTR_STATE, VI_WARN_NSUP_BUF, VI_WARN_NULL_OBJECT, VI_WARN_QUEUE_OVERFLOW, VI_WARN_UNKNOWN_STATUS, EventType, StatusCode, ) completion_and_error_messages = { VI_SUCCESS: ("VI_SUCCESS", "Operation completed successfully."), VI_SUCCESS_EVENT_EN: ( "VI_SUCCESS_EVENT_EN", "Specified event is already enabled for at " "least one of the specified mechanisms.", ), VI_SUCCESS_EVENT_DIS: ( "VI_SUCCESS_EVENT_DIS", "Specified event is already disabled for " "at least one of the specified mechanisms.", ), VI_SUCCESS_QUEUE_EMPTY: ( "VI_SUCCESS_QUEUE_EMPTY", "Operation completed successfully, but " "queue was already empty.", ), VI_SUCCESS_TERM_CHAR: ( "VI_SUCCESS_TERM_CHAR", "The specified termination character was " "read.", ), VI_SUCCESS_MAX_CNT: ( "VI_SUCCESS_MAX_CNT", "The number of bytes transferred is equal " "to the requested input count. More data " "may be available.", ), VI_SUCCESS_DEV_NPRESENT: ( "VI_SUCCESS_DEV_NPRESENT", "Session opened successfully, but the " "device at the specified address is not " "responding.", ), VI_SUCCESS_TRIG_MAPPED: ( "VI_SUCCESS_TRIG_MAPPED", "The path from trigSrc to trigDest is " "already mapped.", ), VI_SUCCESS_QUEUE_NEMPTY: ( "VI_SUCCESS_QUEUE_NEMPTY", "Wait terminated successfully on receipt " "of an event notification. There is at " "least one more event object of the " "requested type(s) available for this " "session.", ), VI_SUCCESS_NCHAIN: ( "VI_SUCCESS_NCHAIN", "Event handled successfully. Do not invoke " "any other handlers on this session for " "this event.", ), VI_SUCCESS_NESTED_SHARED: ( "VI_SUCCESS_NESTED_SHARED", "Operation completed successfully, and " "this session has nested shared locks.", ), VI_SUCCESS_NESTED_EXCLUSIVE: ( "VI_SUCCESS_NESTED_EXCLUSIVE", "Operation completed successfully, and " "this session has nested exclusive locks.", ), VI_SUCCESS_SYNC: ( "VI_SUCCESS_SYNC", "Operation completed successfully, but the " "operation was actually synchronous rather " "than asynchronous.", ), VI_WARN_QUEUE_OVERFLOW: ( "VI_WARN_QUEUE_OVERFLOW", "VISA received more event information of " "the specified type than the configured " "queue size could hold.", ), VI_WARN_CONFIG_NLOADED: ( "VI_WARN_CONFIG_NLOADED", "The specified configuration either does " "not exist or could not be loaded. " "VISA-specified defaults will be used.", ), VI_WARN_NULL_OBJECT: ( "VI_WARN_NULL_OBJECT", "The specified object reference is " "uninitialized.", ), VI_WARN_NSUP_ATTR_STATE: ( "VI_WARN_NSUP_ATTR_STATE", "Although the specified state of the " "attribute is valid, it is not supported " "by this implementation.", ), VI_WARN_UNKNOWN_STATUS: ( "VI_WARN_UNKNOWN_STATUS", "The status code passed to the operation " "could not be interpreted.", ), VI_WARN_NSUP_BUF: ( "VI_WARN_NSUP_BUF", "The specified I/O buffer type is not " "supported.", ), VI_WARN_EXT_FUNC_NIMPL: ( "VI_WARN_EXT_FUNC_NIMPL", "The operation succeeded, but a lower " "level driver did not implement the " "extended functionality.", ), VI_ERROR_SYSTEM_ERROR: ( "VI_ERROR_SYSTEM_ERROR", "Unknown system error (miscellaneous " "error).", ), VI_ERROR_INV_OBJECT: ( "VI_ERROR_INV_OBJECT", "The given session or object reference is " "invalid.", ), VI_ERROR_RSRC_LOCKED: ( "VI_ERROR_RSRC_LOCKED", "Specified type of lock cannot be " "obtained, or specified operation cannot " "be performed, because the resource is " "locked.", ), VI_ERROR_INV_EXPR: ( "VI_ERROR_INV_EXPR", "Invalid expression specified for search.", ), VI_ERROR_RSRC_NFOUND: ( "VI_ERROR_RSRC_NFOUND", "Insufficient location information or the " "requested device or resource is not " "present in the system.", ), VI_ERROR_INV_RSRC_NAME: ( "VI_ERROR_INV_RSRC_NAME", "Invalid resource reference specified. " "Parsing error.", ), VI_ERROR_INV_ACC_MODE: ("VI_ERROR_INV_ACC_MODE", "Invalid access mode."), VI_ERROR_TMO: ("VI_ERROR_TMO", "Timeout expired before operation " "completed."), VI_ERROR_CLOSING_FAILED: ( "VI_ERROR_CLOSING_FAILED", "The VISA driver failed to properly close " "the session or object reference. This " "might be due to an error freeing internal " "or OS resources, a failed network " "connection, or a lower-level driver or OS " "error.", ), VI_ERROR_INV_DEGREE: ("VI_ERROR_INV_DEGREE", "Specified degree is invalid."), VI_ERROR_INV_JOB_ID: ( "VI_ERROR_INV_JOB_ID", "Specified job identifier is invalid.", ), VI_ERROR_NSUP_ATTR: ( "VI_ERROR_NSUP_ATTR", "The specified attribute is not defined or " "supported by the referenced object.", ), VI_ERROR_NSUP_ATTR_STATE: ( "VI_ERROR_NSUP_ATTR_STATE", "The specified state of the attribute is " "not valid, or is not supported as defined " "by the object.", ), VI_ERROR_ATTR_READONLY: ( "VI_ERROR_ATTR_READONLY", "The specified attribute is read-only.", ), VI_ERROR_INV_LOCK_TYPE: ( "VI_ERROR_INV_LOCK_TYPE", "The specified type of lock is not " "supported by this resource.", ), VI_ERROR_INV_ACCESS_KEY: ( "VI_ERROR_INV_ACCESS_KEY", "The access key to the resource associated " "with the specified session is invalid.", ), VI_ERROR_INV_EVENT: ( "VI_ERROR_INV_EVENT", "Specified event type is not supported by " "the resource.", ), VI_ERROR_INV_MECH: ("VI_ERROR_INV_MECH", "Invalid mechanism specified."), VI_ERROR_HNDLR_NINSTALLED: ( "VI_ERROR_HNDLR_NINSTALLED", "A handler was not installed.", ), VI_ERROR_INV_HNDLR_REF: ( "VI_ERROR_INV_HNDLR_REF", "The given handler reference is either " "invalid or was not installed.", ), VI_ERROR_INV_CONTEXT: ( "VI_ERROR_INV_CONTEXT", "Specified event context is invalid.", ), VI_ERROR_QUEUE_OVERFLOW: ( "VI_ERROR_QUEUE_OVERFLOW", "The event queue for the specified type " "has overflowed (usually due to previous " "events not having been closed).", ), VI_ERROR_NENABLED: ( "VI_ERROR_NENABLED", "You must be enabled for events of the " "specified type in order to receive them.", ), VI_ERROR_ABORT: ("VI_ERROR_ABORT", "User abort occurred during transfer."), VI_ERROR_RAW_WR_PROT_VIOL: ( "VI_ERROR_RAW_WR_PROT_VIOL", "Violation of raw write protocol occurred " "during transfer.", ), VI_ERROR_RAW_RD_PROT_VIOL: ( "VI_ERROR_RAW_RD_PROT_VIOL", "Violation of raw read protocol occurred " "during transfer.", ), VI_ERROR_OUTP_PROT_VIOL: ( "VI_ERROR_OUTP_PROT_VIOL", "Device reported an output protocol error " "during transfer.", ), VI_ERROR_INP_PROT_VIOL: ( "VI_ERROR_INP_PROT_VIOL", "Device reported an input protocol error " "during transfer.", ), VI_ERROR_BERR: ("VI_ERROR_BERR", "Bus error occurred during transfer."), VI_ERROR_IN_PROGRESS: ( "VI_ERROR_IN_PROGRESS", "Unable to queue the asynchronous " "operation because there is already an " "operation in progress.", ), VI_ERROR_INV_SETUP: ( "VI_ERROR_INV_SETUP", "Unable to start operation because setup " "is invalid (usually due to attributes " "being set to an inconsistent state).", ), VI_ERROR_QUEUE_ERROR: ( "VI_ERROR_QUEUE_ERROR", "Unable to queue the asynchronous " "operation (usually due to the I/O " "completion event not being enabled or " "insufficient space in the session's " "queue).", ), VI_ERROR_ALLOC: ( "VI_ERROR_ALLOC", "Insufficient system resources to perform " "necessary memory allocation.", ), VI_ERROR_INV_MASK: ("VI_ERROR_INV_MASK", "Invalid buffer mask specified."), VI_ERROR_IO: ( "VI_ERROR_IO", "Could not perform operation because of " "I/O error.", ), VI_ERROR_INV_FMT: ( "VI_ERROR_INV_FMT", "A format specifier in the format string " "is invalid.", ), VI_ERROR_NSUP_FMT: ( "VI_ERROR_NSUP_FMT", "A format specifier in the format string " "is not supported.", ), VI_ERROR_LINE_IN_USE: ( "VI_ERROR_LINE_IN_USE", "The specified trigger line is currently " "in use.", ), VI_ERROR_NSUP_MODE: ( "VI_ERROR_NSUP_MODE", "The specified mode is not supported by " "this VISA implementation.", ), VI_ERROR_SRQ_NOCCURRED: ( "VI_ERROR_SRQ_NOCCURRED", "Service request has not been received for " "the session.", ), VI_ERROR_INV_SPACE: ("VI_ERROR_INV_SPACE", "Invalid address space specified."), VI_ERROR_INV_OFFSET: ("VI_ERROR_INV_OFFSET", "Invalid offset specified."), VI_ERROR_INV_WIDTH: ("VI_ERROR_INV_WIDTH", "Invalid access width specified."), VI_ERROR_NSUP_OFFSET: ( "VI_ERROR_NSUP_OFFSET", "Specified offset is not accessible from " "this hardware.", ), VI_ERROR_NSUP_VAR_WIDTH: ( "VI_ERROR_NSUP_VAR_WIDTH", "Cannot support source and destination " "widths that are different.", ), VI_ERROR_WINDOW_NMAPPED: ( "VI_ERROR_WINDOW_NMAPPED", "The specified session is not currently " "mapped.", ), VI_ERROR_RESP_PENDING: ( "VI_ERROR_RESP_PENDING", "A previous response is still pending, " "causing a multiple query error.", ), VI_ERROR_NLISTENERS: ( "VI_ERROR_NLISTENERS", "No listeners condition is detected (both " "NRFD and NDAC are deasserted).", ), VI_ERROR_NCIC: ( "VI_ERROR_NCIC", "The interface associated with this " "session is not currently the controller " "in charge.", ), VI_ERROR_NSYS_CNTLR: ( "VI_ERROR_NSYS_CNTLR", "The interface associated with this " "session is not the system controller.", ), VI_ERROR_NSUP_OPER: ( "VI_ERROR_NSUP_OPER", "The given session or object reference " "does not support this operation.", ), VI_ERROR_INTR_PENDING: ( "VI_ERROR_INTR_PENDING", "An interrupt is still pending from a " "previous call.", ), VI_ERROR_ASRL_PARITY: ( "VI_ERROR_ASRL_PARITY", "A parity error occurred during transfer.", ), VI_ERROR_ASRL_FRAMING: ( "VI_ERROR_ASRL_FRAMING", "A framing error occurred during transfer.", ), VI_ERROR_ASRL_OVERRUN: ( "VI_ERROR_ASRL_OVERRUN", "An overrun error occurred during " "transfer. A character was not read from " "the hardware before the next character " "arrived.", ), VI_ERROR_TRIG_NMAPPED: ( "VI_ERROR_TRIG_NMAPPED", "The path from trigSrc to trigDest is not " "currently mapped.", ), VI_ERROR_NSUP_ALIGN_OFFSET: ( "VI_ERROR_NSUP_ALIGN_OFFSET", "The specified offset is not properly " "aligned for the access width of the " "operation.", ), VI_ERROR_USER_BUF: ( "VI_ERROR_USER_BUF", "A specified user buffer is not valid or " "cannot be accessed for the required size.", ), VI_ERROR_RSRC_BUSY: ( "VI_ERROR_RSRC_BUSY", "The resource is valid, but VISA cannot " "currently access it.", ), VI_ERROR_NSUP_WIDTH: ( "VI_ERROR_NSUP_WIDTH", "Specified width is not supported by this " "hardware.", ), VI_ERROR_INV_PARAMETER: ( "VI_ERROR_INV_PARAMETER", "The value of some parameter (which " "parameter is not known) is invalid.", ), VI_ERROR_INV_PROT: ("VI_ERROR_INV_PROT", "The protocol specified is invalid."), VI_ERROR_INV_SIZE: ("VI_ERROR_INV_SIZE", "Invalid size of window specified."), VI_ERROR_WINDOW_MAPPED: ( "VI_ERROR_WINDOW_MAPPED", "The specified session currently contains " "a mapped window.", ), VI_ERROR_NIMPL_OPER: ( "VI_ERROR_NIMPL_OPER", "The given operation is not implemented.", ), VI_ERROR_INV_LENGTH: ("VI_ERROR_INV_LENGTH", "Invalid length specified."), VI_ERROR_INV_MODE: ("VI_ERROR_INV_MODE", "Invalid mode specified."), VI_ERROR_SESN_NLOCKED: ( "VI_ERROR_SESN_NLOCKED", "The current session did not have a lock " "on the resource.", ), VI_ERROR_MEM_NSHARED: ( "VI_ERROR_MEM_NSHARED", "The device does not export any memory.", ), VI_ERROR_LIBRARY_NFOUND: ( "VI_ERROR_LIBRARY_NFOUND", "A code library required by VISA could not " "be located or loaded.", ), VI_ERROR_NSUP_INTR: ( "VI_ERROR_NSUP_INTR", "The interface cannot generate an " "interrupt on the requested level or with " "the requested statusID value.", ), VI_ERROR_INV_LINE: ( "VI_ERROR_INV_LINE", "The value specified by the line parameter " "is invalid.", ), VI_ERROR_FILE_ACCESS: ( "VI_ERROR_FILE_ACCESS", "An error occurred while trying to open " "the specified file. Possible reasons " "include an invalid path or lack of access " "rights.", ), VI_ERROR_FILE_IO: ( "VI_ERROR_FILE_IO", "An error occurred while performing I/O on " "the specified file.", ), VI_ERROR_NSUP_LINE: ( "VI_ERROR_NSUP_LINE", "One of the specified lines (trigSrc or " "trigDest) is not supported by this VISA " "implementation, or the combination of " "lines is not a valid mapping.", ), VI_ERROR_NSUP_MECH: ( "VI_ERROR_NSUP_MECH", "The specified mechanism is not supported " "for the given event type.", ), VI_ERROR_INTF_NUM_NCONFIG: ( "VI_ERROR_INTF_NUM_NCONFIG", "The interface type is valid but the " "specified interface number is not " "configured.", ), VI_ERROR_CONN_LOST: ( "VI_ERROR_CONN_LOST", "The connection for the given session has " "been lost.", ), VI_ERROR_MACHINE_NAVAIL: ( "VI_ERROR_MACHINE_NAVAIL", "The remote machine does not exist or is " "not accepting any connections. If the " "NI-VISA server is installed and running " "on the remote machine, it may have an " "incompatible version or may be listening " "on a different port.", ), VI_ERROR_NPERMISSION: ( "VI_ERROR_NPERMISSION", "Access to the resource or remote machine " "is denied. This is due to lack of " "sufficient privileges for the current " "user or machine", ), } default_warnings = frozenset( [ StatusCode.success_max_count_read, StatusCode.success_device_not_present, StatusCode.success_synchronous, StatusCode.warning_queue_overflow, StatusCode.warning_configuration_not_loaded, StatusCode.warning_null_object, StatusCode.warning_nonsupported_attribute_state, StatusCode.warning_unknown_status, StatusCode.warning_unknown_status, StatusCode.warning_nonsupported_buffer, StatusCode.warning_ext_function_not_implemented, ] ) class Error(Exception): """Abstract basic exception class for this module.""" pass class VisaIOError(Error): """Exception class for VISA I/O errors. Please note that all values for "error_code" are negative according to the specification (VPP-4.3.2, observation 3.3.2) and the NI implementation. """ def __init__(self, error_code: int) -> None: abbreviation, description = completion_and_error_messages.get( error_code, ("?", "Unknown code.") ) super(VisaIOError, self).__init__( "%s (%d): %s" % (abbreviation, error_code, description) ) self.error_code = error_code self.abbreviation = abbreviation self.description = description def __reduce__(self) -> Tuple[type, Tuple[int]]: """Store the error code when pickling.""" return (VisaIOError, (self.error_code,)) class VisaIOWarning(Warning): """Exception class for VISA I/O warnings. According to the specification VPP-4.3.2 and the NI implementation. """ def __init__(self, error_code: int) -> None: abbreviation, description = completion_and_error_messages.get( error_code, ("?", "Unknown code.") ) super(VisaIOWarning, self).__init__( "%s (%d): %s" % (abbreviation, error_code, description) ) self.error_code = error_code self.abbreviation = abbreviation self.description = description def __reduce__(self) -> Tuple[type, Tuple[int]]: """Store the error code when pickling.""" return (VisaIOWarning, (self.error_code,)) class VisaTypeError(Error): """Exception class for wrong types in VISA function argument lists. Raised if unsupported types are given to scanf, sscanf, printf, sprintf, and queryf. Because the current implementation doesn't analyse the format strings, it can only deal with integers, floats, and strings. Additionally, this exception is raised by install_handler if un unsupported type is used for the user handle. """ class UnknownHandler(Error): """Exception class for invalid handler data given to uninstall_handler(). uninstall_handler() checks whether the handler and user_data parameters point to a known handler previously installed with install_handler(). If it can't find it, this exception is raised. """ def __init__( self, event_type: EventType, handler: typing.VISAHandler, user_handle: Any ) -> None: super(UnknownHandler, self).__init__( "%s, %s, %s" % (event_type, handler, user_handle) ) self.event_type = event_type self.handler = handler self.user_handle = user_handle def __reduce__(self) -> Tuple[type, tuple]: """Store the event type, handler and user handle when pickling.""" return (UnknownHandler, (self.event_type, self.handler, self.user_handle)) class OSNotSupported(Error): """Exception used when dealing with an unsuported OS.""" def __init__(self, os: str) -> None: super(OSNotSupported, self).__init__(os + " is not yet supported by PyVISA") self.os = os def __reduce__(self) -> Tuple[type, Tuple[str]]: """Store the os name when pickling.""" return (OSNotSupported, (self.os,)) class InvalidBinaryFormat(Error): """Exception used when the specified binary format is incorrect.""" def __init__(self, description: str = "") -> None: desc = ": " + description if description else "" super(InvalidBinaryFormat, self).__init__( "Unrecognized binary data format" + desc ) self.description = description def __reduce__(self) -> Tuple[type, tuple]: """Store the description when pickling.""" return (InvalidBinaryFormat, (self.description,)) class InvalidSession(Error): """Exception raised when an invalid session is requested.""" def __init__(self) -> None: super(InvalidSession, self).__init__( "Invalid session handle. The resource might be closed." ) def __reduce__(self) -> Tuple[type, tuple]: """Nothing to store when pickling.""" return (InvalidSession, ()) class LibraryError(OSError, Error): """Exception used when an issue occurs loading the VISA library.""" @classmethod def from_exception(cls, exc: Exception, filename: str) -> "LibraryError": """Build the exception from a lower level exception.""" try: msg = str(exc) if ": image not found" in msg: msg = " File not found or not readable." elif ": no suitable image found" in msg: if "no matching architecture" in msg: return LibraryError.from_wrong_arch(filename) else: msg = "Could not determine filetype." elif "wrong ELF class" in msg: return LibraryError.from_wrong_arch(filename) except UnicodeDecodeError: return cls("Error while accessing %s." % filename) return cls("Error while accessing %s: %s" % (filename, msg)) @classmethod def from_wrong_arch(cls, filename: str) -> "LibraryError": """Build the exception when the library has a mismatched architecture.""" s = "" details = util.get_system_details(backends=False) visalib = util.LibraryPath( 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 += " The library in: %s\n" % visalib.path s += " found by: %s\n" % visalib.found_by s += " bitness: %s\n" % visalib.bitness return cls("Error while accessing %s: %s" % (filename, s)) # TODO remove when removing return handler def _args_to_str(args: tuple, kwargs: dict) -> str: # pragma: no cover return "args=%s, kwargs=%s" % (args, kwargs) def return_handler(module_logger, first_is_session=True): # pragma: no cover """Decorate a VISA library function returning an error code.""" warnings.warn("return_handler will be removed in 1.12", FutureWarning) def _outer(visa_library_method): def _inner(self, session, *args, **kwargs): ret_value = visa_library_method(*args, **kwargs) module_logger.debug( "%s%s -> %r", visa_library_method.__name__, _args_to_str(args, kwargs), ret_value, ) try: ret_value = StatusCode(ret_value) except ValueError: pass if first_is_session: self._last_status = ret_value self._last_status_in_session[session] = ret_value if ret_value < 0: raise VisaIOError(ret_value) if ret_value in self.issue_warning_on: if ( session and ret_value not in self._ignore_warning_in_session[session] ): module_logger.warn(VisaIOWarning(ret_value), stacklevel=2) return ret_value return _inner return _outer pyvisa-1.11.3/pyvisa/events.py000066400000000000000000000171301375165327600163220ustar00rootroot00000000000000# -*- coding: utf-8 -*- """VISA events with convenient access to the available attributes. This file is part of PyVISA. :copyright: 2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ from typing import TYPE_CHECKING, Callable, Dict, Optional, Type from typing_extensions import ClassVar from . import attributes, constants, errors, logger from .attributes import Attribute from .typing import Any, VISAEventContext, VISAJobID if TYPE_CHECKING: from . import highlevel # pragma: no cover class Event: """Event that lead to the call of an event handler. Do not instantiate directly use the visa_event context manager of the Resource object passed to the handler. Notes ----- When using the queuing mechanism events are expected to be closed manually after handling them. When using callbacks, the events should only be closed if VISA will never get control again which since we always attempt to properly close all resources should never happend and hence events should never be closed manually. """ #: Reference to the visa library visalib: "highlevel.VisaLibraryBase" #: Type of the event. event_type: constants.EventType #: Context use to query the event attributes. _context: Optional[VISAEventContext] #: Maps Event type to Python class encapsulating that event. _event_classes: ClassVar[Dict[constants.EventType, Type["Event"]]] = dict() @classmethod def register( cls, event_type: constants.EventType ) -> Callable[[Type["Event"]], Type["Event"]]: """Register a class with a given event type.""" def _internal(python_class: Type["Event"]) -> Type["Event"]: if event_type in cls._event_classes: logger.warning( "%s is already registered. " "Overwriting with %s" % (event_type, python_class) ) for attr in attributes.AttributesPerResource[event_type]: if not hasattr(python_class, attr.py_name): raise TypeError( "%s is expected to have an attribute %s" % (python_class, attr.py_name) ) cls._event_classes[event_type] = python_class return python_class return _internal def __new__( cls, visalib: "highlevel.VisaLibraryBase", event_type: constants.EventType, context: VISAEventContext, ) -> "Event": event_cls = cls._event_classes.get(event_type, Event) return object.__new__(event_cls) def __init__( self, visalib: "highlevel.VisaLibraryBase", event_type: constants.EventType, context: Optional[VISAEventContext], ) -> None: self.visalib = visalib self.event_type = event_type self._context = context @property def context(self) -> VISAEventContext: """Access the VISA context used to retrieve attributes. This is equivalent to the session on a resource. """ c = self._context if c is None: raise errors.InvalidSession() return c def get_visa_attribute(self, attribute_id: constants.EventAttribute) -> Any: """Get the specified VISA attribute.""" return self.visalib.get_attribute(self.context, attribute_id)[0] def close(self): """Simply invalidate the context. The event is not closed since it is only ever required when using the queue mechanism and this is handled in WaitResponse. """ self._context = None # Those events do not have any payload beyond their type, for those use the base class for event in ( constants.EventType.clear, constants.EventType.service_request, constants.EventType.gpib_listen, constants.EventType.gpib_talk, constants.EventType.vxi_vme_sysfail, constants.EventType.vxi_vme_sysreset, ): Event.register(event)(Event) @Event.register(constants.EventType.exception) class ExceptionEvent(Event): """Event corresponding to an exception.""" #: Status code of the operation that generated the exception status: Attribute[constants.StatusCode] = attributes.AttrVI_ATTR_STATUS() #: Name of the operation that led to the exception operation_name: Attribute[str] = attributes.AttrVI_ATTR_OPER_NAME() @Event.register(constants.EventType.gpib_controller_in_charge) class GPIBCICEvent(Event): """GPIB Controller in Charge event. The event is emitted if the status is gained or lost. """ #: New state of the controller in charge status cic_state: Attribute[ constants.LineState ] = attributes.AttrVI_ATTR_GPIB_RECV_CIC_STATE() @Event.register(constants.EventType.io_completion) class IOCompletionEvent(Event): """Event marking the completion of an IO operation.""" #: Status code of the asynchronous I/O operation that has completed. status: Attribute[constants.StatusCode] = attributes.AttrVI_ATTR_STATUS() #: Buffer that was used in an asynchronous operation. buffer: Attribute[bytes] = attributes.AttrVI_ATTR_BUFFER() #: Actual number of elements that were asynchronously transferred. return_count: Attribute[int] = attributes.AttrVI_ATTR_RET_COUNT() #: Name of the operation generating the event. operation_name: Attribute[str] = attributes.AttrVI_ATTR_OPER_NAME() #: Job ID of the asynchronous operation that has completed. job_id: Attribute[VISAJobID] = attributes.AttrVI_ATTR_JOB_ID() @property def data(self): """Portion of the buffer that was actually filled during the call.""" return bytes(self.buffer[: self.return_count]) @Event.register(constants.EventType.trig) class TrigEvent(Event): """Trigger event.""" #: Identifier of the triggering mechanism on which the specified trigger event #: was received. received_trigger_id: Attribute[ constants.TriggerID ] = attributes.AttrVI_ATTR_TRIG_ID() @Event.register(constants.EventType.usb_interrupt) class USBInteruptEvent(Event): """USB interruption event.""" #: Status of the read operation from the USB interrupt-IN pipe. status: Attribute[constants.StatusCode] = attributes.AttrVI_ATTR_STATUS() #: Size of the data that was received from the USB interrupt-IN pipe. size: Attribute[int] = attributes.AttrVI_ATTR_USB_RECV_INTR_SIZE() #: Actual data that was received from the USB interrupt-IN pipe. data = attributes.AttrVI_ATTR_USB_RECV_INTR_DATA() @Event.register(constants.EventType.vxi_signal_interrupt) class VXISignalInteruptEvent(Event): """VXI signal event.""" #: 16-bit Status/ID value retrieved during the IACK cycle or #: from the Signal register. signal_register_status_id: Attribute[int] = attributes.AttrVI_ATTR_SIGP_STATUS_ID() @Event.register(constants.EventType.vxi_vme_interrupt) class VXIInterruptEvent(Event): """VXI interrupt event.""" #: 32-bit status/ID retrieved during the IACK cycle. status_id: Attribute[int] = attributes.AttrVI_ATTR_INTR_STATUS_ID() #: VXI interrupt level on which the interrupt was received. level: Attribute[int] = attributes.AttrVI_ATTR_RECV_INTR_LEVEL() @Event.register(constants.EventType.pxi_interrupt) class PXIInteruptEvent(Event): """PXI interruption event.""" #: Index of the interrupt sequence that detected the interrupt condition. sequence: Attribute[int] = attributes.AttrVI_ATTR_PXI_RECV_INTR_SEQ() #: First PXI/PCI register read in the successful interrupt detection sequence. data: Attribute[int] = attributes.AttrVI_ATTR_PXI_RECV_INTR_DATA() pyvisa-1.11.3/pyvisa/highlevel.py000066400000000000000000003205051375165327600167700ustar00rootroot00000000000000# -*- coding: utf-8 -*- """High level Visa library wrapper. This file is part of PyVISA. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ import atexit import contextlib import copy import os import pkgutil import warnings from collections import defaultdict from importlib import import_module from itertools import chain from types import ModuleType from typing import ( TYPE_CHECKING, Any, Callable, ContextManager, Dict, Iterable, Iterator, List, NamedTuple, Optional, Set, SupportsBytes, Tuple, Type, TypeVar, Union, cast, ) from weakref import WeakMethod, WeakSet, WeakValueDictionary from typing_extensions import ClassVar, DefaultDict, Literal from . import attributes, constants, errors, logger, rname from .constants import StatusCode from .typing import ( VISAEventContext, VISAHandler, VISAJobID, VISAMemoryAddress, VISARMSession, VISASession, ) from .util import LibraryPath if TYPE_CHECKING: from .resources import Resource # pragma: no cover #: Resource extended information #: #: Named tuple with information about a resource. Returned by some :class:`ResourceManager` methods. #: #: :interface_type: Interface type of the given resource string. :class:`pyvisa.constants.InterfaceType` #: :interface_board_number: Board number of the interface of the given resource string. We allow None #: since serial resources may not sometimes be easily described #: by a single number in particular on Linux system. #: :resource_class: Specifies the resource class (for example, "INSTR") of the given resource string. #: :resource_name: This is the expanded version of the given resource string. #: The format should be similar to the VISA-defined canonical resource name. #: :alias: Specifies the user-defined alias for the given resource string. ResourceInfo = NamedTuple( "ResourceInfo", ( ("interface_type", constants.InterfaceType), ("interface_board_number", Optional[int]), ("resource_class", Optional[str]), ("resource_name", Optional[str]), ("alias", Optional[str]), ), ) # Used to properly type the __new__ method T = TypeVar("T", bound="VisaLibraryBase") class VisaLibraryBase(object): """Base for VISA library classes. A class derived from `VisaLibraryBase` library provides the low-level communication to the underlying devices providing Pythonic wrappers to VISA functions. But not all derived class must/will implement all methods. Even if methods are expected to return the status code they are expected to raise the appropriate exception when an error ocurred since this is more Pythonic. The default VisaLibrary class is :class:`pyvisa.ctwrapper.highlevel.IVIVisaLibrary`, which implements a ctypes wrapper around the IVI-VISA library. Certainly, IVI-VISA can be NI-VISA, Keysight VISA, R&S VISA, tekVISA etc. In general, you should not instantiate it directly. The object exposed to the user is the :class:`pyvisa.highlevel.ResourceManager`. If needed, you can access the VISA library from it:: >>> import pyvisa >>> rm = pyvisa.ResourceManager("/path/to/my/libvisa.so.7") >>> lib = rm.visalib """ #: Default ResourceManager instance for this library. resource_manager: Optional["ResourceManager"] #: Path to the VISA library used by this instance library_path: LibraryPath #: Maps library path to VisaLibrary object _registry: ClassVar[ Dict[Tuple[Type["VisaLibraryBase"], LibraryPath], "VisaLibraryBase"] ] = WeakValueDictionary() # type: ignore #: Last return value of the library. _last_status: StatusCode = StatusCode(0) #: Maps session handle to last status. _last_status_in_session: Dict[ Union[VISASession, VISARMSession, VISAEventContext], StatusCode ] #: Maps session handle to warnings to ignore. _ignore_warning_in_session: Dict[int, set] #: Extra inforatoion used for logging errors _logging_extra: Dict[str, str] #: Contains all installed event handlers. #: Its elements are tuples with four elements: The handler itself (a Python #: callable), the user handle (in any format making sense to the lower level #: implementation, ie as a ctypes object for the ctypes backend) and the #: handler again, this time in a format meaningful to the backend (ie as a #: ctypes object created with CFUNCTYPE for the ctypes backend) and #: the event type. handlers: DefaultDict[VISASession, List[Tuple[VISAHandler, Any, Any, Any]]] #: Set error codes on which to issue a warning. issue_warning_on: Set[StatusCode] def __new__( cls: Type[T], library_path: Union[str, LibraryPath] = "" ) -> "VisaLibraryBase": """Create a new VISA library from the specified path. If a library was already created using the same path and class this library object is returned instead. Parameters ---------- library_path : str | LibraryPath Path to the VISA library to use in the backend. Raises ------ OSError Raised if the VISA library object could not be created. """ if library_path == "": errs = [] for path in cls.get_library_paths(): try: return cls(path) except OSError as e: logger.debug("Could not open VISA library %s: %s", path, str(e)) errs.append(str(e)) except Exception as e: errs.append(str(e)) else: raise OSError("Could not open VISA library:\n" + "\n".join(errs)) if not isinstance(library_path, LibraryPath): lib_path = LibraryPath(library_path, "user specified") else: lib_path = library_path if (cls, lib_path) in cls._registry: return cls._registry[(cls, lib_path)] obj = super(VisaLibraryBase, cls).__new__(cls) obj.library_path = lib_path obj._logging_extra = {"library_path": obj.library_path} obj._init() # Create instance specific registries. #: Error codes on which to issue a warning. obj.issue_warning_on = set(errors.default_warnings) obj._last_status_in_session = dict() obj._ignore_warning_in_session = defaultdict(set) obj.handlers = defaultdict(list) obj.resource_manager = None logger.debug("Created library wrapper for %s", lib_path) cls._registry[(cls, lib_path)] = obj return obj @staticmethod def get_library_paths() -> Iterable[LibraryPath]: """Override to list the possible library_paths if no path is specified.""" return () @staticmethod def get_debug_info() -> Union[Iterable[str], Dict[str, Union[str, Dict[str, Any]]]]: """Override to return an iterable of lines with the backend debug details.""" return ["Does not provide debug info"] def _init(self) -> None: """Override this method to customize VisaLibrary initialization.""" pass def __str__(self) -> str: """str representation of the library.""" return "Visa Library at %s" % self.library_path def __repr__(self) -> str: """str representation of the library including the type of the library.""" return "<%s(%r)>" % (type(self).__name__, self.library_path) def handle_return_value( self, session: Optional[Union[VISAEventContext, VISARMSession, VISASession]], status_code: int, ) -> StatusCode: """Helper function handling the return code of a low-level operation. Used when implementing concrete subclasses of VISALibraryBase. """ rv: StatusCode try: rv = StatusCode(status_code) except ValueError: rv = cast(StatusCode, status_code) self._last_status = rv if session is not None: self._last_status_in_session[session] = rv if rv < 0: raise errors.VisaIOError(rv) if rv in self.issue_warning_on: if session and rv not in self._ignore_warning_in_session[session]: warnings.warn(errors.VisaIOWarning(rv), stacklevel=2) # Return the original value for further processing. return rv @property def last_status(self) -> StatusCode: """Last return value of the library.""" return self._last_status def get_last_status_in_session( self, session: Union[VISASession, VISARMSession] ) -> StatusCode: """Last status in session. Helper function to be called by resources properties. """ try: return self._last_status_in_session[session] except KeyError: raise errors.Error( "The session %r does not seem to be valid as it does not have any last status" % session ) @contextlib.contextmanager def ignore_warning( self, session: Union[VISASession, VISARMSession], *warnings_constants: StatusCode, ) -> Iterator: """Ignore warnings for a session for the duration of the context. Parameters ---------- session : Union[VISASession, VISARMSession] Unique logical identifier to a session. warnings_constants : StatusCode Constants identifying the warnings to ignore. """ self._ignore_warning_in_session[session].update(warnings_constants) yield self._ignore_warning_in_session[session].difference_update(warnings_constants) def install_visa_handler( self, session: VISASession, event_type: constants.EventType, handler: VISAHandler, user_handle: Any = None, ) -> Any: """Installs handlers for event callbacks. Parameters ---------- session : VISASession Unique logical identifier to a session. event_type : constants.EventType, Logical event identifier. handler : VISAHandler Handler to be installed by a client application. user_handle : A value specified by an application that can be used for identifying handlers uniquely for an event type. Returns ------- converted_user_handle: Converted user handle to match the underlying library. This version of the handle should be used in further call to the library. """ try: new_handler = self.install_handler( session, event_type, handler, user_handle ) except TypeError as e: raise errors.VisaTypeError(str(e)) from e self.handlers[session].append(new_handler[:-1] + (event_type,)) return new_handler[1] def uninstall_visa_handler( self, session: VISASession, event_type: constants.EventType, handler: VISAHandler, user_handle: Any = None, ) -> None: """Uninstalls handlers for events. Parameters ---------- session : VISASession Unique logical identifier to a session. event_type : constants.EventType Logical event identifier. handler : VISAHandler Handler to be uninstalled by a client application. user_handle : The user handle returned by install_visa_handler. """ for ndx, element in enumerate(self.handlers[session]): # use == rather than is to allow bound methods as handlers if ( element[0] == handler and element[1] is user_handle and element[3] == event_type ): del self.handlers[session][ndx] break else: raise errors.UnknownHandler(event_type, handler, user_handle) self.uninstall_handler(session, event_type, element[2], user_handle) def __uninstall_all_handlers_helper(self, session: VISASession) -> None: """Uninstall all VISA handlers for a given session.""" for element in self.handlers[session]: self.uninstall_handler(session, element[3], element[2], element[1]) del self.handlers[session] def uninstall_all_visa_handlers(self, session: Optional[VISASession]) -> None: """Uninstalls all previously installed handlers for a particular session. Parameters ---------- session : VISASession | None Unique logical identifier to a session. If None, operates on all sessions. """ if session is not None: self.__uninstall_all_handlers_helper(session) else: for session in list(self.handlers): self.__uninstall_all_handlers_helper(session) def read_memory( self, session: VISASession, space: constants.AddressSpace, offset: int, width: Union[Literal[8, 16, 32, 64], constants.DataWidth], extended: bool = False, ) -> Tuple[int, StatusCode]: """Read a value from the specified memory space and offset. Corresponds to viIn* functions of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Specifies the address space from which to read. offset : int Offset (in bytes) of the address or register from which to read. width : Union[Literal[8, 16, 32, 64], constants.DataWidth] Number of bits to read (8, 16, 32 or 64). extended : bool, optional Use 64 bits offset independent of the platform. Returns ------- data : int Data read from memory status_code : StatusCode Return value of the library call. Raises ------ ValueError Raised if an invalid width is specified. """ w = width * 8 if isinstance(width, constants.DataWidth) else width if w not in (8, 16, 32, 64): raise ValueError( "%s is not a valid size. Valid values are 8, 16, 32 or 64 " "or one member of constants.DataWidth" % width ) return getattr(self, f"in_{w}")(session, space, offset, extended) def write_memory( self, session: VISASession, space: constants.AddressSpace, offset: int, data: int, width: Union[Literal[8, 16, 32, 64], constants.DataWidth], extended: bool = False, ) -> StatusCode: """Write a value to the specified memory space and offset. Parameters ---------- session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Specifies the address space. offset : int Offset (in bytes) of the address or register from which to read. data : int Data to write to bus. width : Union[Literal[8, 16, 32, 64], constants.DataWidth] Number of bits to read. extended : bool, optional Use 64 bits offset independent of the platform, by default False. Returns ------- StatusCode Return value of the library call. Raises ------ ValueError Raised if an invalid width is specified. """ w = width * 8 if isinstance(width, constants.DataWidth) else width if w not in (8, 16, 32, 64): raise ValueError( "%s is not a valid size. Valid values are 8, 16, 32 or 64 " "or one member of constants.DataWidth" % width ) return getattr(self, f"out_{w}")(session, space, offset, data, extended) def move_in( self, session: VISASession, space: constants.AddressSpace, offset: int, length: int, width: Union[Literal[8, 16, 32, 64], constants.DataWidth], extended: bool = False, ) -> Tuple[List[int], StatusCode]: """Move a block of data to local memory from the given address space and offset. Corresponds to viMoveIn* functions of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space from which to move the data. offset : int Offset (in bytes) of the address or register from which to read. length : int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. width : Union[Literal[8, 16, 32, 64], constants.DataWidth] Number of bits to read per element. extended : bool, optional Use 64 bits offset independent of the platform, by default False. Returns ------- data : List[int] Data read from the bus status_code : StatusCode Return value of the library call. Raises ------ ValueError Raised if an invalid width is specified. """ w = width * 8 if isinstance(width, constants.DataWidth) else width if w not in (8, 16, 32, 64): raise ValueError( "%s is not a valid size. Valid values are 8, 16, 32 or 64 " "or one member of constants.DataWidth" % width ) return getattr(self, f"move_in_{w}")(session, space, offset, length, extended) def move_out( self, session: VISASession, space: constants.AddressSpace, offset: int, length: int, data: Iterable[int], width: Union[Literal[8, 16, 32, 64], constants.DataWidth], extended: bool = False, ) -> StatusCode: """Move a block of data from local memory to the given address space and offset. Corresponds to viMoveOut* functions of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space into which move the data. offset : int Offset (in bytes) of the address or register from which to read. length : int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. data : Iterable[int] Data to write to bus. width : Union[Literal[8, 16, 32, 64], constants.DataWidth] Number of bits to per element. extended : bool, optional Use 64 bits offset independent of the platform, by default False. Returns ------- StatusCode Return value of the library call. Raises ------ ValueError Raised if an invalid width is specified. """ w = width * 8 if isinstance(width, constants.DataWidth) else width if w not in (8, 16, 32, 64): raise ValueError( "%s is not a valid size. Valid values are 8, 16, 32 or 64 " "or one member of constants.DataWidth" % width ) return getattr(self, f"move_out_{w}")( session, space, offset, length, data, extended ) def peek( self, session: VISASession, address: VISAMemoryAddress, width: Union[Literal[8, 16, 32, 64], constants.DataWidth], ) -> Tuple[int, StatusCode]: """Read an 8, 16, 32, or 64-bit value from the specified address. Corresponds to viPeek* functions of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. address : VISAMemoryAddress Source address to read the value. width : Union[Literal[8, 16, 32, 64], constants.DataWidth] Number of bits to read. Returns ------- data : int Data read from bus status_code : StatusCode Return value of the library call. Raises ------ ValueError Raised if an invalid width is specified. """ w = width * 8 if isinstance(width, constants.DataWidth) else width if w not in (8, 16, 32, 64): raise ValueError( "%s is not a valid size. Valid values are 8, 16, 32 or 64 " "or one member of constants.DataWidth" % width ) return getattr(self, f"peek_{w}")(session, address) def poke( self, session: VISASession, address: VISAMemoryAddress, width: Union[Literal[8, 16, 32, 64], constants.DataWidth], data: int, ) -> StatusCode: """Writes an 8, 16, 32, or 64-bit value from the specified address. Corresponds to viPoke* functions of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. address : VISAMemoryAddress Source address to read the value. width : Union[Literal[8, 16, 32, 64], constants.DataWidth] Number of bits to read. data : int Data to write to the bus Returns ------- status_code : StatusCode Return value of the library call. Raises ------ ValueError Raised if an invalid width is specified. """ w = width * 8 if isinstance(width, constants.DataWidth) else width if w not in (8, 16, 32, 64): raise ValueError( "%s is not a valid size. Valid values are 8, 16, 32 or 64 " "or one member of constants.DataWidth" % width ) return getattr(self, f"poke_{w}")(session, address, data) # Methods that VISA Library implementations must implement def assert_interrupt_signal( self, session: VISASession, mode: constants.AssertSignalInterrupt, status_id: int, ) -> StatusCode: """Asserts the specified interrupt or signal. Corresponds to viAssertIntrSignal function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. mode : constants.AssertSignalInterrupt How to assert the interrupt. status_id : int Status value to be presented during an interrupt acknowledge cycle. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def assert_trigger( self, session: VISASession, protocol: constants.TriggerProtocol ) -> StatusCode: """Assert software or hardware trigger. Corresponds to viAssertTrigger function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. protocol : constants.TriggerProtocol Trigger protocol to use during assertion. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def assert_utility_signal( self, session: VISASession, line: constants.UtilityBusSignal ) -> StatusCode: """Assert or deassert the specified utility bus signal. Corresponds to viAssertUtilSignal function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. line : constants.UtilityBusSignal Specifies the utility bus signal to assert. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def buffer_read(self, session: VISASession, count: int) -> Tuple[bytes, StatusCode]: """Reads data through the use of a formatted I/O read buffer. The data can be read from a device or an interface. Corresponds to viBufRead function of the VISA library. Parameters ---------- session : VISASession\ Unique logical identifier to a session. count : int Number of bytes to be read. Returns ------- dbytes Data read StatusCode Return value of the library call. """ raise NotImplementedError def buffer_write(self, session: VISASession, data: bytes) -> Tuple[int, StatusCode]: """Writes data to a formatted I/O write buffer synchronously. Corresponds to viBufWrite function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. data : bytes Data to be written. Returns ------- int number of written bytes StatusCode return value of the library call. """ raise NotImplementedError def clear(self, session: VISASession) -> StatusCode: """Clears a device. Corresponds to viClear function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def close( self, session: Union[VISASession, VISAEventContext, VISARMSession] ) -> StatusCode: """Closes the specified session, event, or find list. Corresponds to viClose function of the VISA library. Parameters --------- session : Union[VISASession, VISAEventContext, VISARMSession] Unique logical identifier to a session, event, resource manager. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def disable_event( self, session: VISASession, event_type: constants.EventType, mechanism: constants.EventMechanism, ) -> StatusCode: """Disable notification for an event type(s) via the specified mechanism(s). Corresponds to viDisableEvent function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. event_type : constants.EventType Event type. mechanism : constants.EventMechanism Event handling mechanisms to be disabled. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def discard_events( self, session: VISASession, event_type: constants.EventType, mechanism: constants.EventMechanism, ) -> StatusCode: """Discard event occurrences for a given type and mechanisms in a session. Corresponds to viDiscardEvents function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. event_type : constans.EventType Logical event identifier. mechanism : constants.EventMechanism Specifies event handling mechanisms to be discarded. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def enable_event( self, session: VISASession, event_type: constants.EventType, mechanism: constants.EventMechanism, context: None = None, ) -> StatusCode: """Enable event occurrences for specified event types and mechanisms in a session. Corresponds to viEnableEvent function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. event_type : constants.EventType Logical event identifier. mechanism : constants.EventMechanism Specifies event handling mechanisms to be enabled. context : None, optional Unused parameter... Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def flush( self, session: VISASession, mask: constants.BufferOperation ) -> StatusCode: """Flush the specified buffers. The buffers can be associated with formatted I/O operations and/or serial communication. Corresponds to viFlush function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. mask : constants.BufferOperation Specifies the action to be taken with flushing the buffer. The values can be combined using the | operator. However multiple operations on a single buffer cannot be combined. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def get_attribute( self, session: Union[VISASession, VISAEventContext, VISARMSession], attribute: Union[constants.ResourceAttribute, constants.EventAttribute], ) -> Tuple[Any, StatusCode]: """Retrieves the state of an attribute. Corresponds to viGetAttribute function of the VISA library. Parameters ---------- session : Union[VISASession, VISAEventContext] Unique logical identifier to a session, event, or find list. attribute : Union[constants.ResourceAttribute, constants.EventAttribute] Resource or event attribute for which the state query is made. Returns ------- Any State of the queried attribute for a specified resource StatusCode Return value of the library call. """ raise NotImplementedError def gpib_command(self, session: VISASession, data: bytes) -> Tuple[int, StatusCode]: """Write GPIB command bytes on the bus. Corresponds to viGpibCommand function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. data : bytes Data to write. Returns ------- int Number of written bytes StatusCode Return value of the library call. """ raise NotImplementedError def gpib_control_atn( self, session: VISASession, mode: constants.ATNLineOperation ) -> StatusCode: """Specifies the state of the ATN line and the local active controller state. Corresponds to viGpibControlATN function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. mode : constants.ATNLineOperation State of the ATN line and optionally the local active controller state. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def gpib_control_ren( self, session: VISASession, mode: constants.RENLineOperation ) -> StatusCode: """Controls the state of the GPIB Remote Enable (REN) interface line. Optionally the remote/local state of the device can also be set. Corresponds to viGpibControlREN function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. mode : constants.RENLineOperation State of the REN line and optionally the device remote/local state. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def gpib_pass_control( self, session: VISASession, primary_address: int, secondary_address: int ) -> StatusCode: """Tell a GPIB device to become controller in charge (CIC). Corresponds to viGpibPassControl function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. primary_address : int Primary address of the GPIB device to which you want to pass control. secondary_address : int Secondary address of the targeted GPIB device. If the targeted device does not have a secondary address, this parameter should contain the value Constants.VI_NO_SEC_ADDR. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def gpib_send_ifc(self, session: VISASession) -> StatusCode: """Pulse the interface clear line (IFC) for at least 100 microseconds. Corresponds to viGpibSendIFC function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def in_8( self, session: VISASession, space: constants.AddressSpace, offset: int, extended: bool = False, ) -> Tuple[int, StatusCode]: """Reads in an 8-bit value from the specified memory space and offset. Corresponds to viIn8* function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Specifies the address space. offset : int Offset (in bytes) of the address or register from which to read. extended : bool, optional Use 64 bits offset independent of the platform, False by default. Returns ------- int Data read from memory StatusCode Return value of the library call. """ raise NotImplementedError def in_16( self, session: VISASession, space: constants.AddressSpace, offset: int, extended: bool = False, ) -> Tuple[int, StatusCode]: """Reads in an 16-bit value from the specified memory space and offset. Corresponds to viIn16* function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Specifies the address space. offset : int Offset (in bytes) of the address or register from which to read. extended : bool, optional Use 64 bits offset independent of the platform, False by default. Returns ------- int Data read from memory StatusCode Return value of the library call. """ raise NotImplementedError def in_32( self, session: VISASession, space: constants.AddressSpace, offset: int, extended: bool = False, ) -> Tuple[int, StatusCode]: """Reads in an 32-bit value from the specified memory space and offset. Corresponds to viIn32* function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Specifies the address space. offset : int Offset (in bytes) of the address or register from which to read. extended : bool, optional Use 64 bits offset independent of the platform, False by default. Returns ------- int Data read from memory StatusCode Return value of the library call. """ raise NotImplementedError def in_64( self, session: VISASession, space: constants.AddressSpace, offset: int, extended: bool = False, ) -> Tuple[int, StatusCode]: """Reads in an 64-bit value from the specified memory space and offset. Corresponds to viIn64* function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Specifies the address space. offset : int Offset (in bytes) of the address or register from which to read. extended : bool, optional Use 64 bits offset independent of the platform, False by default. Returns ------- int Data read from memory StatusCode Return value of the library call. """ raise NotImplementedError def install_handler( self, session: VISASession, event_type: constants.EventType, handler: VISAHandler, user_handle: Any, ) -> Tuple[VISAHandler, Any, Any, StatusCode]: """Install handlers for event callbacks. Corresponds to viInstallHandler function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. event_type : constants.EventType Logical event identifier. handler : VISAHandler Reference to a handler to be installed by a client application. user_handle : Any Value specified by an application that can be used for identifying handlers uniquely for an event type. Returns ------- handler : VISAHandler Handler to be installed by a client application. converted_user_handle : Converted user handle to match the underlying library. This version of the handle should be used in further call to the library. converted_handler : Converted version of the handler satisfying to backend library. status_code : StatusCode Return value of the library call """ raise NotImplementedError def list_resources( self, session: VISARMSession, query: str = "?*::INSTR" ) -> Tuple[str, ...]: """Return a tuple of all connected devices matching query. Parameters ---------- session : VISARMSession Unique logical identifier to the resource manager session. query : str Regular expression used to match devices. Returns ------- Tuple[str, ...] Resource names of all the connected devices matching the query. """ raise NotImplementedError def lock( self, session: VISASession, lock_type: constants.Lock, timeout: int, requested_key: Optional[str] = None, ) -> Tuple[str, StatusCode]: """Establishes an access mode to the specified resources. Corresponds to viLock function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. lock_type : constants.Lock Specifies the type of lock requested. timeout : int Absolute time period (in milliseconds) that a resource waits to get unlocked by the locking session before returning an error. requested_key : Optional[str], optional Requested locking key in the case of a shared lock. For an exclusive lock it should be None. Returns ------- Optional[str] Key that can then be passed to other sessions to share the lock, or None for an exclusive lock. StatusCode Return value of the library call. """ raise NotImplementedError def map_address( self, session: VISASession, map_space: constants.AddressSpace, map_base: int, map_size: int, access: Literal[False] = False, suggested: Optional[int] = None, ) -> Tuple[int, StatusCode]: """Maps the specified memory space into the process's address space. Corresponds to viMapAddress function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. map_space : constants.AddressSpace Specifies the address space to map. map_base : int Offset (in bytes) of the memory to be mapped. map_size : int Amount of memory to map (in bytes). access : False Unused parameter. suggested : Optional[int], optional If not None, the operating system attempts to map the memory to the address specified. There is no guarantee, however, that the memory will be mapped to that address. This operation may map the memory into an address region different from the suggested one. Returns ------- int Address in your process space where the memory was mapped StatusCode Return value of the library call. """ raise NotImplementedError def map_trigger( self, session: VISASession, trigger_source: constants.InputTriggerLine, trigger_destination: constants.OutputTriggerLine, mode: None = None, ) -> StatusCode: """Map the specified trigger source line to the specified destination line. Corresponds to viMapTrigger function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. trigger_source : constants.InputTriggerLine Source line from which to map. trigger_destination : constants.OutputTriggerLine Destination line to which to map. mode : None, optional Always None for this version of the VISA specification. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def memory_allocation( self, session: VISASession, size: int, extended: bool = False ) -> Tuple[int, StatusCode]: """Allocate memory from a resource's memory region. Corresponds to viMemAlloc* functions of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. size : int Specifies the size of the allocation. extended : bool, optional Use 64 bits offset independent of the platform. Returns ------- int offset of the allocated memory StatusCode Return value of the library call. """ raise NotImplementedError def memory_free( self, session: VISASession, offset: int, extended: bool = False ) -> StatusCode: """Frees memory previously allocated using the memory_allocation() operation. Corresponds to viMemFree* function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. offset : int Offset of the memory to free. extended : bool, optional Use 64 bits offset independent of the platform. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def move( self, session: VISASession, source_space: constants.AddressSpace, source_offset: int, source_width: constants.DataWidth, destination_space: constants.AddressSpace, destination_offset: int, destination_width: constants.DataWidth, length: int, ) -> StatusCode: """Moves a block of data. Corresponds to viMove function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. source_space : constants.AddressSpace Specifies the address space of the source. source_offset : int Offset of the starting address or register from which to read. source_width : constants.DataWidth Specifies the data width of the source. destination_space : constants.AddressSpace Specifies the address space of the destination. destination_offset : int Offset of the starting address or register to which to write. destination_width : constants.DataWidth Specifies the data width of the destination. length: int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def move_asynchronously( self, session: VISASession, source_space: constants.AddressSpace, source_offset: int, source_width: constants.DataWidth, destination_space: constants.AddressSpace, destination_offset: int, destination_width: constants.DataWidth, length: int, ) -> Tuple[VISAJobID, StatusCode]: """Moves a block of data asynchronously. Corresponds to viMoveAsync function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. source_space : constants.AddressSpace Specifies the address space of the source. source_offset : int Offset of the starting address or register from which to read. source_width : constants.DataWidth Specifies the data width of the source. destination_space : constants.AddressSpace Specifies the address space of the destination. destination_offset : int Offset of the starting address or register to which to write. destination_width : constants.DataWidth Specifies the data width of the destination. length : int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. Returns ------- VISAJobID Job identifier of this asynchronous move operation StatusCode Return value of the library call. """ raise NotImplementedError def move_in_8( self, session: VISASession, space: constants.AddressSpace, offset: int, length: int, extended: bool = False, ) -> Tuple[List[int], StatusCode]: """Moves an 8-bit block of data to local memory. Corresponds to viMoveIn8* functions of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space from which to move the data. offset : int Offset (in bytes) of the address or register from which to read. length : int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. extended : bool, optional Use 64 bits offset independent of the platform, by default False. Returns ------- data : List[int] Data read from the bus status_code : StatusCode Return value of the library call. """ raise NotImplementedError def move_in_16( self, session: VISASession, space: constants.AddressSpace, offset: int, length: int, extended: bool = False, ) -> Tuple[List[int], StatusCode]: """Moves an 16-bit block of data to local memory. Corresponds to viMoveIn816 functions of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space from which to move the data. offset : int Offset (in bytes) of the address or register from which to read. length : int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. extended : bool, optional Use 64 bits offset independent of the platform, by default False. Returns ------- data : List[int] Data read from the bus status_code : StatusCode Return value of the library call. """ raise NotImplementedError def move_in_32( self, session: VISASession, space: constants.AddressSpace, offset: int, length: int, extended: bool = False, ) -> Tuple[List]: """Moves an 32-bit block of data to local memory. Corresponds to viMoveIn32* functions of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space from which to move the data. offset : int Offset (in bytes) of the address or register from which to read. length : int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. extended : bool, optional Use 64 bits offset independent of the platform, by default False. Returns ------- data : List[int] Data read from the bus status_code : StatusCode Return value of the library call. """ raise NotImplementedError def move_in_64( self, session: VISASession, space: constants.AddressSpace, offset: int, length: int, extended: bool = False, ) -> Tuple[List[int], StatusCode]: """Moves an 64-bit block of data to local memory. Corresponds to viMoveIn8* functions of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space from which to move the data. offset : int Offset (in bytes) of the address or register from which to read. length : int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. extended : bool, optional Use 64 bits offset independent of the platform, by default False. Returns ------- data : List[int] Data read from the bus status_code : StatusCode Return value of the library call. """ raise NotImplementedError def move_out_8( self, session: VISASession, space: constants.AddressSpace, offset: int, length: int, data: Iterable[int], extended: bool = False, ) -> StatusCode: """Moves an 8-bit block of data from local memory. Corresponds to viMoveOut8* functions of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space into which move the data. offset : int Offset (in bytes) of the address or register from which to read. length : int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. data : Iterable[int] Data to write to bus. extended : bool, optional Use 64 bits offset independent of the platform, by default False. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def move_out_16( self, session: VISASession, space: constants.AddressSpace, offset: int, length: int, data: Iterable[int], extended: bool = False, ) -> StatusCode: """Moves an 16-bit block of data from local memory. Corresponds to viMoveOut16* functions of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space into which move the data. offset : int Offset (in bytes) of the address or register from which to read. length : int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. data : Iterable[int] Data to write to bus. extended : bool, optional Use 64 bits offset independent of the platform, by default False. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def move_out_32( self, session: VISASession, space: constants.AddressSpace, offset: int, length: int, data: Iterable[int], extended: bool = False, ) -> StatusCode: """Moves an 32-bit block of data from local memory. Corresponds to viMoveOut32* functions of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space into which move the data. offset : int Offset (in bytes) of the address or register from which to read. length : int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. data : Iterable[int] Data to write to bus. extended : bool, optional Use 64 bits offset independent of the platform, by default False. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def move_out_64( self, session: VISASession, space: constants.AddressSpace, offset: int, length: int, data: Iterable[int], extended: bool = False, ) -> StatusCode: """Moves an 64-bit block of data from local memory. Corresponds to viMoveOut64* functions of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space into which move the data. offset : int Offset (in bytes) of the address or register from which to read. length : int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. data : Iterable[int] Data to write to bus. extended : bool, optional Use 64 bits offset independent of the platform, by default False. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def open( self, session: VISARMSession, resource_name: str, access_mode: constants.AccessModes = constants.AccessModes.no_lock, open_timeout: int = constants.VI_TMO_IMMEDIATE, ) -> Tuple[VISASession, StatusCode]: """Opens a session to the specified resource. Corresponds to viOpen function of the VISA library. Parameters ---------- session : VISARMSession Resource Manager session (should always be a session returned from open_default_resource_manager()). resource_name : str Unique symbolic name of a resource. access_mode : constants.AccessModes, optional Specifies the mode by which the resource is to be accessed. open_timeout : int If the ``access_mode`` parameter requests a lock, then this parameter specifies the absolute time period (in milliseconds) that the resource waits to get unlocked before this operation returns an error. Returns ------- VISASession Unique logical identifier reference to a session StatusCode Return value of the library call. """ raise NotImplementedError def open_default_resource_manager(self) -> Tuple[VISARMSession, StatusCode]: """This function returns a session to the Default Resource Manager resource. Corresponds to viOpenDefaultRM function of the VISA library. Returns ------- VISARMSession Unique logical identifier to a Default Resource Manager session StatusCode Return value of the library call. """ raise NotImplementedError def out_8( self, session: VISASession, space: constants.AddressSpace, offset: int, data: int, extended: bool = False, ) -> StatusCode: """Write an 8-bit value to the specified memory space and offset. Corresponds to viOut8* functions of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space into which to write. offset : int Offset (in bytes) of the address or register from which to read. data : int Data to write to bus. extended : bool, optional Use 64 bits offset independent of the platform. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def out_16( self, session: VISASession, space: constants.AddressSpace, offset: int, data: int, extended: bool = False, ) -> StatusCode: """Write a 16-bit value to the specified memory space and offset. Corresponds to viOut16* functions of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space into which to write. offset : int Offset (in bytes) of the address or register from which to read. data : int Data to write to bus. extended : bool, optional Use 64 bits offset independent of the platform. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def out_32( self, session: VISASession, space: constants.AddressSpace, offset: int, data: Iterable[int], extended: bool = False, ) -> StatusCode: """Write a 32-bit value to the specified memory space and offset. Corresponds to viOut32* functions of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space into which to write. offset : int Offset (in bytes) of the address or register from which to read. data : int Data to write to bus. extended : bool, optional Use 64 bits offset independent of the platform. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def out_64( self, session: VISASession, space: constants.AddressSpace, offset: int, data: Iterable[int], extended: bool = False, ) -> StatusCode: """Write a 64-bit value to the specified memory space and offset. Corresponds to viOut64* functions of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. space : constants.AddressSpace Address space into which to write. offset : int Offset (in bytes) of the address or register from which to read. data : int Data to write to bus. extended : bool, optional Use 64 bits offset independent of the platform. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def parse_resource( self, session: VISARMSession, resource_name: str ) -> Tuple[ResourceInfo, StatusCode]: """Parse a resource string to get the interface information. Corresponds to viParseRsrc function of the VISA library. Parameters ---------- session : VISARMSession Resource Manager session (should always be the Default Resource Manager for VISA returned from open_default_resource_manager()). resource_name : str Unique symbolic name of a resource. Returns ------- ResourceInfo Resource information with interface type and board number StatusCode Return value of the library call. """ ri, status = self.parse_resource_extended(session, resource_name) if status == StatusCode.success: return ( ResourceInfo( ri.interface_type, ri.interface_board_number, None, None, None ), StatusCode.success, ) else: return ri, status def parse_resource_extended( self, session: VISARMSession, resource_name: str ) -> Tuple[ResourceInfo, StatusCode]: """Parse a resource string to get extended interface information. Corresponds to viParseRsrcEx function of the VISA library. Parameters ---------- session : VISARMSession Resource Manager session (should always be the Default Resource Manager for VISA returned from open_default_resource_manager()). resource_name : str Unique symbolic name of a resource. Returns ------- ResourceInfo Resource information with interface type and board number StatusCode Return value of the library call. """ try: parsed = rname.parse_resource_name(resource_name) except ValueError: return ( ResourceInfo(constants.InterfaceType.unknown, 0, None, None, None), StatusCode.error_invalid_resource_name, ) board_number: Optional[int] try: # We can only get concrete classes which have one of those attributes board_number = int( parsed.board # type: ignore if hasattr(parsed, "board") else parsed.interface # type: ignore ) # In some cases the board number may not be convertible to an int # PyVISA-py serial resources on Linux for example except ValueError: board_number = None return ( ResourceInfo( parsed.interface_type_const, board_number, parsed.resource_class, str(parsed), None, ), StatusCode.success, ) def peek_8( self, session: VISASession, address: VISAMemoryAddress ) -> Tuple[int, StatusCode]: """Read an 8-bit value from the specified address. Corresponds to viPeek8 function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. address : VISAMemoryAddress Source address to read the value. Returns ------- int Data read from bus StatusCode Return value of the library call. """ raise NotImplementedError def peek_16( self, session: VISASession, address: VISAMemoryAddress ) -> Tuple[int, StatusCode]: """Read an 16-bit value from the specified address. Corresponds to viPeek16 function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. address : VISAMemoryAddress Source address to read the value. Returns ------- int Data read from bus StatusCode Return value of the library call. """ raise NotImplementedError def peek_32( self, session: VISASession, address: VISAMemoryAddress ) -> Tuple[int, StatusCode]: """Read an 32-bit value from the specified address. Corresponds to viPeek32 function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. address : VISAMemoryAddress Source address to read the value. Returns ------- int Data read from bus StatusCode Return value of the library call. """ raise NotImplementedError def peek_64( self, session: VISASession, address: VISAMemoryAddress ) -> Tuple[int, StatusCode]: """Read an 64-bit value from the specified address. Corresponds to viPeek64 function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. address : VISAMemoryAddress Source address to read the value. Returns ------- int Data read from bus StatusCode Return value of the library call. """ raise NotImplementedError def poke_8( self, session: VISASession, address: VISAMemoryAddress, data: int ) -> StatusCode: """Write an 8-bit value to the specified address. Corresponds to viPoke8 function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. address : VISAMemoryAddress Source address to read the value. data : int Data to write. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def poke_16( self, session: VISASession, address: VISAMemoryAddress, data: int ) -> StatusCode: """Write an 16-bit value to the specified address. Corresponds to viPoke16 function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. address : VISAMemoryAddress Source address to read the value. data : int Data to write. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def poke_32( self, session: VISASession, address: VISAMemoryAddress, data: int ) -> StatusCode: """Write an 32-bit value to the specified address. Corresponds to viPoke32 function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. address : VISAMemoryAddress Source address to read the value. data : int Data to write. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def poke_64( self, session: VISASession, address: VISAMemoryAddress, data: int ) -> StatusCode: """Write an 64-bit value to the specified address. Corresponds to viPoke64 function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. address : VISAMemoryAddress Source address to read the value. data : int Data to write. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def read(self, session: VISASession, count: int) -> Tuple[bytes, StatusCode]: """Reads data from device or interface synchronously. Corresponds to viRead function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. count : int Number of bytes to be read. Returns ------- bytes Date read StatusCode Return value of the library call. """ raise NotImplementedError def read_asynchronously( self, session: VISASession, count: int ) -> Tuple[SupportsBytes, VISAJobID, StatusCode]: """Reads data from device or interface asynchronously. Corresponds to viReadAsync function of the VISA library. Since the asynchronous operation may complete before the function call return implementation should make sure that get_buffer_from_id will be able to return the proper buffer before this method returns. Parameters ---------- session : VISASession Unique logical identifier to a session. count : int Number of bytes to be read. Returns ------- SupportsBytes Buffer that will be filled during the asynchronous operation. VISAJobID Id of the asynchronous job StatusCode Return value of the library call. """ raise NotImplementedError def get_buffer_from_id(self, job_id: VISAJobID) -> Optional[SupportsBytes]: """Retrieve the buffer associated with a job id created in read_asynchronously Parameters ---------- job_id : VISAJobID Id of the job for which to retrieve the buffer. Returns ------- Optional[SupportsBytes] Buffer in which the data are stored or None if the job id is not associated with any job. """ raise NotImplementedError def read_stb(self, session: VISASession) -> Tuple[int, StatusCode]: """Reads a status byte of the service request. Corresponds to viReadSTB function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. Returns ------- int Service request status byte StatusCode Return value of the library call. """ raise NotImplementedError def read_to_file( self, session: VISASession, filename: str, count: int ) -> Tuple[int, StatusCode]: """Read data synchronously, and store the transferred data in a file. Corresponds to viReadToFile function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. filename : str Name of file to which data will be written. count : int Number of bytes to be read. Returns ------- int Number of bytes actually transferred StatusCode Return value of the library call. """ raise NotImplementedError def set_attribute( self, session: VISASession, attribute: constants.ResourceAttribute, attribute_state: Any, ) -> StatusCode: """Set the state of an attribute. Corresponds to viSetAttribute function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. attribute : constants.ResourceAttribute Attribute for which the state is to be modified. attribute_state : Any The state of the attribute to be set for the specified object. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def set_buffer( self, session: VISASession, mask: constants.BufferType, size: int ) -> StatusCode: """Set the size for the formatted I/O and/or low-level I/O communication buffer(s). Corresponds to viSetBuf function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. mask : constants.BufferType Specifies the type of buffer. size : int The size to be set for the specified buffer(s). Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def status_description( self, session: VISASession, status: StatusCode ) -> Tuple[str, StatusCode]: """Return a user-readable description of the status code passed to the operation. Corresponds to viStatusDesc function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. status : StatusCode Status code to interpret. Returns ------- str User-readable string interpretation of the status code. StatusCode Return value of the library call. """ raise NotImplementedError def terminate( self, session: VISASession, degree: None, job_id: VISAJobID ) -> StatusCode: """Request a VISA session to terminate normal execution of an operation. Corresponds to viTerminate function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. degree : None Not used in this version of the VISA specification. job_id : VISAJobId Specifies an operation identifier. If a user passes None as the job_id value to viTerminate(), a VISA implementation should abort any calls in the current process executing on the specified vi. Any call that is terminated this way should return VI_ERROR_ABORT. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def uninstall_handler( self, session: VISASession, event_type: constants.EventType, handler: VISAHandler, user_handle: Any = None, ) -> StatusCode: """Uninstall handlers for events. Corresponds to viUninstallHandler function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. event_type : constants.EventType Logical event identifier. handler : VISAHandler Handler to be uninstalled by a client application. user_handle: A value specified by an application that can be used for identifying handlers uniquely in a session for an event. The modified value of the user_handle as returned by install_handler should be used instead of the original value. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def unlock(self, session: VISASession) -> StatusCode: """Relinquish a lock for the specified resource. Corresponds to viUnlock function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def unmap_address(self, session: VISASession) -> StatusCode: """Unmap memory space previously mapped by map_address(). Corresponds to viUnmapAddress function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def unmap_trigger( self, session: VISASession, trigger_source: constants.InputTriggerLine, trigger_destination: constants.OutputTriggerLine, ) -> StatusCode: """Undo a previous map between a trigger source line and a destination line. Corresponds to viUnmapTrigger function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. trigger_source : constants.InputTriggerLine Source line used in previous map. trigger_destination : constants.OutputTriggerLine Destination line used in previous map. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def usb_control_in( self, session: VISASession, request_type_bitmap_field: int, request_id: int, request_value: int, index: int, length: int = 0, ) -> Tuple[bytes, StatusCode]: """Perform a USB control pipe transfer from the device. Corresponds to viUsbControlIn function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. request_type_bitmap_field : int bmRequestType parameter of the setup stage of a USB control transfer. request_id : int bRequest parameter of the setup stage of a USB control transfer. request_value : int wValue parameter of the setup stage of a USB control transfer. index : int wIndex parameter of the setup stage of a USB control transfer. This is usually the index of the interface or endpoint. length : int, optional wLength parameter of the setup stage of a USB control transfer. This value also specifies the size of the data buffer to receive the data from the optional data stage of the control transfer. Returns ------- bytes The data buffer that receives the data from the optional data stage of the control transfer StatusCode Return value of the library call. """ raise NotImplementedError def usb_control_out( self, session: VISASession, request_type_bitmap_field: int, request_id: int, request_value: int, index: int, data: bytes = b"", ) -> StatusCode: """Perform a USB control pipe transfer to the device. Corresponds to viUsbControlOut function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. request_type_bitmap_field : int bmRequestType parameter of the setup stage of a USB control transfer. request_id : int bRequest parameter of the setup stage of a USB control transfer. request_value : int wValue parameter of the setup stage of a USB control transfer. index : int wIndex parameter of the setup stage of a USB control transfer. This is usually the index of the interface or endpoint. data : bytes, optional The data buffer that sends the data in the optional data stage of the control transfer. Returns ------- StatusCode Return value of the library call. """ raise NotImplementedError def vxi_command_query( self, session: VISASession, mode: constants.VXICommands, command: int ) -> Tuple[int, StatusCode]: """Send the device a miscellaneous command or query and/or retrieves the response to a previous query. Corresponds to viVxiCommandQuery function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. mode : constants.VXICommands Specifies whether to issue a command and/or retrieve a response. command : int The miscellaneous command to send. Returns ------- int The response retrieved from the device StatusCode Return value of the library call. """ raise NotImplementedError def wait_on_event( self, session: VISASession, in_event_type: constants.EventType, timeout: int ) -> Tuple[constants.EventType, VISAEventContext, StatusCode]: """Wait for an occurrence of the specified event for a given session. Corresponds to viWaitOnEvent function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. in_event_type : constants.EventType Logical identifier of the event(s) to wait for. timeout : int Absolute time period in time units that the resource shall wait for a specified event to occur before returning the time elapsed error. The time unit is in milliseconds. Returns ------- constants.EventType Logical identifier of the event actually received VISAEventContext A handle specifying the unique occurrence of an event StatusCode Return value of the library call. """ raise NotImplementedError def write(self, session: VISASession, data: bytes) -> Tuple[int, StatusCode]: """Write data to device or interface synchronously. Corresponds to viWrite function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. data : bytes Data to be written. Returns ------- int Number of bytes actually transferred StatusCode Return value of the library call. """ raise NotImplementedError def write_asynchronously( self, session: VISASession, data: bytes ) -> Tuple[VISAJobID, StatusCode]: """Write data to device or interface asynchronously. Corresponds to viWriteAsync function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. data : bytes Data to be written. Returns ------- VISAJobID Job ID of this asynchronous write operation StatusCode Return value of the library call. """ raise NotImplementedError def write_from_file( self, session: VISASession, filename: str, count: int ) -> Tuple[int, StatusCode]: """Take data from a file and write it out synchronously. Corresponds to viWriteFromFile function of the VISA library. Parameters ---------- session : VISASession Unique logical identifier to a session. filename : str Name of file from which data will be read. count : int Number of bytes to be written. Returns ------- int Number of bytes actually transferred StatusCode Return value of the library call. """ raise NotImplementedError def list_backends() -> List[str]: """Return installed backends. Backends are installed python packages named pyvisa_ where is the name of the backend. """ return ["ivi"] + [ name[7:] for (loader, name, ispkg) in pkgutil.iter_modules() if (name.startswith("pyvisa_") or name.startswith("pyvisa-")) and not name.endswith("-script") ] #: Maps backend name to VisaLibraryBase derived class _WRAPPERS: Dict[str, Type[VisaLibraryBase]] = {} class PyVISAModule(ModuleType): WRAPPER_CLASS: Type[VisaLibraryBase] def get_wrapper_class(backend_name: str) -> Type[VisaLibraryBase]: """Return the WRAPPER_CLASS for a given backend. backend_name == 'ni' is used for backwards compatibility and will be removed in 1.12. """ try: return _WRAPPERS[backend_name] except KeyError: if backend_name == "ivi" or backend_name == "ni": from .ctwrapper import IVIVisaLibrary _WRAPPERS["ivi"] = IVIVisaLibrary if backend_name == "ni": warnings.warn( "@ni backend name is deprecated and will be " "removed in 1.12. Use @ivi instead. " "Check the documentation for details", FutureWarning, ) return IVIVisaLibrary pkg: PyVISAModule try: pkg = cast(PyVISAModule, import_module("pyvisa_" + backend_name)) _WRAPPERS[backend_name] = cls = pkg.WRAPPER_CLASS return cls except ImportError: try: pkg = cast(PyVISAModule, import_module("pyvisa-" + backend_name)) _WRAPPERS[backend_name] = cls = pkg.WRAPPER_CLASS warnings.warn( "Backends packages should use an _ rather than a - ." "Project can/should keep using a - (like pytest plugins)." "Support for backends with - will be removed in 1.12", FutureWarning, ) return cls except ImportError: raise ValueError( "Wrapper not found: No package named pyvisa_%s" % backend_name ) def _get_default_wrapper() -> str: """Return an available default VISA wrapper as a string ('ivi' or 'py'). Use IVI if the binary is found, else try to use pyvisa-py. 'ni' VISA wrapper is NOT used since version > 1.10.0 and will be removed in 1.12 Raises ------ ValueError If no backend can be found """ from .ctwrapper import IVIVisaLibrary ivi_binary_found = bool(IVIVisaLibrary.get_library_paths()) if ivi_binary_found: logger.debug("The IVI implementation available") return "ivi" else: logger.debug("Did not find IVI binary") try: get_wrapper_class("py") # check for pyvisa-py availability logger.debug("pyvisa-py is available.") return "py" except ValueError: logger.debug("Did not find pyvisa-py package") raise ValueError( "Could not locate a VISA implementation. Install either the IVI binary or pyvisa-py." ) def open_visa_library(specification: str = "") -> VisaLibraryBase: """Helper function to create a VISA library wrapper. In general, you should not use the function directly. The VISA library wrapper will be created automatically when you create a ResourceManager object. Parameters ---------- specification : str, optional The specification has 2 parts separated by a '@', ex: path/visa.dll@ivi The second part is the backend name (ivi, py, ...) while the first part will be passed to the library object. In the case of the ivi backend it should the path to the VISA library. Either part can be omitted. If the second part is omitted, the system will fall back to the ivi backend if available or the pyvisa-py backend if the first part is also omitted. """ if not specification: logger.debug("No visa library specified, trying to find alternatives.") try: specification = os.environ["PYVISA_LIBRARY"] except KeyError: logger.debug("Environment variable PYVISA_LIBRARY is unset.") wrapper: Optional[str] try: argument, wrapper = specification.split("@") except ValueError: argument = specification wrapper = None # Flag that we need a fallback, but avoid nested exceptions if wrapper is None: if argument: # some filename given wrapper = "ivi" else: wrapper = _get_default_wrapper() cls = get_wrapper_class(wrapper) try: return cls(argument) except Exception as e: logger.debug("Could not open VISA wrapper %s: %s\n%s", cls, str(argument), e) raise class ResourceManager(object): """VISA Resource Manager. """ #: Maps (Interface Type, Resource Class) to Python class encapsulating that resource. _resource_classes: ClassVar[ Dict[Tuple[constants.InterfaceType, str], Type["Resource"]] ] = dict() #: Session handler for the resource manager. _session: Optional[VISARMSession] = None #: Reference to the VISA library used by the ResourceManager visalib: VisaLibraryBase #: Resources created by this manager to allow closing them when the manager is closed _created_resources: WeakSet #: Handler for atexit using a weakref to close _atexit_handler: Callable @classmethod def register_resource_class( cls, interface_type: constants.InterfaceType, resource_class: str, python_class: Type["Resource"], ) -> None: """Register a class for a specific interface type, resource class pair. Parameters ---------- interface_type : constants.InterfaceTyp Interface type for which to use the provided class. resource_class : str Resource class (INSTR, INTFC, ...) for which to use teh povided class. python_class : Type[Resource] Subclass of ``Resource`` to use when opening a resource matching the specified interface type and resource class. """ if (interface_type, resource_class) in cls._resource_classes: logger.warning( "%s is already registered in the ResourceManager. " "Overwriting with %s" % ((interface_type, resource_class), python_class) ) # If the class already has this attribute, it means that a parent class # was registered first. We need to copy the current set and extend it. attrs = copy.copy(getattr(python_class, "visa_attributes_classes", set())) for attr in chain( attributes.AttributesPerResource[(interface_type, resource_class)], attributes.AttributesPerResource[attributes.AllSessionTypes], ): attrs.add(attr) # Error on non-properly set descriptor (this ensures that we are # consistent) if attr.py_name != "" and not hasattr(python_class, attr.py_name): raise TypeError( "%s was expected to have a visa attribute %s" % (python_class, attr.py_name) ) setattr(python_class, "visa_attributes_classes", attrs) cls._resource_classes[(interface_type, resource_class)] = python_class def __new__( cls: Type["ResourceManager"], visa_library: Union[str, VisaLibraryBase] = "" ) -> "ResourceManager": """Create a new resource manager tied to the specified VISA library. Parameters ---------- visa_library : Union[str, VisaLibraryBase] Either a fully initialized VisaLibraryBase subclass instance or a str specification (see open_visa_library for the format). """ if not isinstance(visa_library, VisaLibraryBase): visa_library = open_visa_library(visa_library) if visa_library.resource_manager is not None: obj = visa_library.resource_manager logger.debug("Reusing ResourceManager with session %s", obj.session) return obj obj = super(ResourceManager, cls).__new__(cls) obj.session, err = visa_library.open_default_resource_manager() obj.visalib = visa_library obj.visalib.resource_manager = obj obj._created_resources = WeakSet() # Register an atexit handler to ensure the Resource Manager is properly # closed. close_ref = WeakMethod(obj.close) # type: ignore def call_close(): meth = close_ref() if meth: meth() atexit.register(call_close) obj._atexit_handler = call_close # type: ignore logger.debug("Created ResourceManager with session %s", obj.session) return obj @property def session(self) -> VISARMSession: """Resource Manager session handle. Raises ------ errors.InvalidSession Raised if the session is closed. """ if self._session is None: raise errors.InvalidSession() return self._session @session.setter def session(self, value: Optional[VISARMSession]) -> None: self._session = value def __str__(self) -> str: return "Resource Manager of %s" % self.visalib def __repr__(self) -> str: return "" % self.visalib def __del__(self) -> None: if self._session is not None: self.close() def ignore_warning(self, *warnings_constants: StatusCode) -> ContextManager: """Ignoring warnings context manager for the current resource. Parameters ---------- warnings_constants : StatusCode Constants identifying the warnings to ignore. """ return self.visalib.ignore_warning(self.session, *warnings_constants) @property def last_status(self) -> StatusCode: """Last status code returned for an operation with this Resource Manager.""" return self.visalib.get_last_status_in_session(self.session) def close(self) -> None: """Close the resource manager session.""" atexit.unregister(self._atexit_handler) try: logger.debug("Closing ResourceManager (session: %s)", self.session) # Cleanly close all resources when closing the manager. for resource in self._created_resources: resource.close() self.visalib.close(self.session) # mypy don't get that we can set a value we cannot get self.session = None # type: ignore self.visalib.resource_manager = None except errors.InvalidSession: pass def list_resources(self, query: str = "?*::INSTR") -> Tuple[str, ...]: r"""Return a tuple of all connected devices matching query. Notes ----- The query uses the VISA Resource Regular Expression syntax - which is not the same as the Python regular expression syntax. (see below) The VISA Resource Regular Expression syntax is defined in the VISA Library specification: http://www.ivifoundation.org/docs/vpp43.pdf Symbol Meaning ---------- ---------- ? Matches any one character. \ Makes the character that follows it an ordinary character instead of special character. For example, when a question mark follows a backslash (\?), it matches the ? character instead of any one character. [list] Matches any one character from the enclosed list. You can use a hyphen to match a range of characters. [^list] Matches any character not in the enclosed list. You can use a hyphen to match a range of characters. * Matches 0 or more occurrences of the preceding character or expression. + Matches 1 or more occurrences of the preceding character or expression. Exp|exp Matches either the preceding or following expression. The or operator | matches the entire expression that precedes or follows it and not just the character that precedes or follows it. For example, VXI|GPIB means (VXI)|(GPIB), not VX(I|G)PIB. (exp) Grouping characters or expressions. Thus the default query, '?*::INSTR', matches any sequences of characters ending ending with '::INSTR'. On some platforms, devices that are already open are not returned. """ return self.visalib.list_resources(self.session, query) def list_resources_info(self, query: str = "?*::INSTR") -> Dict[str, ResourceInfo]: """Get extended information about all connected devices matching query. For details of the VISA Resource Regular Expression syntax used in query, refer to list_resources(). Returns ------- Dict[str, ResourceInfo] Mapping of resource name to ResourceInfo """ return dict( (resource, self.resource_info(resource)) for resource in self.list_resources(query) ) def list_opened_resources(self) -> List["Resource"]: """Return a list of all the opened resources.""" opened = [] for resource in self._created_resources: try: resource.session except errors.InvalidSession: pass else: opened.append(resource) return opened def resource_info(self, resource_name: str, extended: bool = True) -> ResourceInfo: """Get the (extended) information of a particular resource. Parameters ---------- resource_name : str Unique symbolic name of a resource. extended : bool, optional Also get extended information (ie. resource_class, resource_name, alias) """ if extended: ret, err = self.visalib.parse_resource_extended(self.session, resource_name) else: ret, err = self.visalib.parse_resource(self.session, resource_name) return ret def open_bare_resource( self, resource_name: str, access_mode: constants.AccessModes = constants.AccessModes.no_lock, open_timeout: int = constants.VI_TMO_IMMEDIATE, ) -> Tuple[VISASession, StatusCode]: """Open the specified resource without wrapping into a class. Parameters ---------- resource_name : str Name or alias of the resource to open. access_mode : constants.AccessModes, optional Specifies the mode by which the resource is to be accessed, by default constants.AccessModes.no_lock open_timeout : int, optional If the ``access_mode`` parameter requests a lock, then this parameter specifies the absolute time period (in milliseconds) that the resource waits to get unlocked before this operation returns an error, by default constants.VI_TMO_IMMEDIATE. Returns ------- VISASession Unique logical identifier reference to a session. StatusCode Return value of the library call. """ return self.visalib.open(self.session, resource_name, access_mode, open_timeout) def open_resource( self, resource_name: str, access_mode: constants.AccessModes = constants.AccessModes.no_lock, open_timeout: int = constants.VI_TMO_IMMEDIATE, resource_pyclass: Optional[Type["Resource"]] = None, **kwargs: Any, ) -> "Resource": """Return an instrument for the resource name. Parameters ---------- resource_name : str Name or alias of the resource to open. access_mode : constants.AccessModes, optional Specifies the mode by which the resource is to be accessed, by default constants.AccessModes.no_lock open_timeout : int, optional If the ``access_mode`` parameter requests a lock, then this parameter specifies the absolute time period (in milliseconds) that the resource waits to get unlocked before this operation returns an error, by default constants.VI_TMO_IMMEDIATE. resource_pyclass : Optional[Type[Resource]], optional Resource Python class to use to instantiate the Resource. Defaults to None: select based on the resource name. kwargs : Any Keyword arguments to be used to change instrument attributes after construction. Returns ------- Resource Subclass of Resource matching the resource. """ if resource_pyclass is None: info = self.resource_info(resource_name, extended=True) try: # When using querying extended resource info the resource_class is not # None resource_pyclass = self._resource_classes[ (info.interface_type, info.resource_class) # type: ignore ] except KeyError: resource_pyclass = self._resource_classes[ (constants.InterfaceType.unknown, "") ] logger.warning( "There is no class defined for %r. Using Resource", (info.interface_type, info.resource_class), ) res = resource_pyclass(self, resource_name) for key in kwargs.keys(): try: getattr(res, key) present = True except AttributeError: present = False except errors.InvalidSession: present = True if not present: raise ValueError( "%r is not a valid attribute for type %s" % (key, res.__class__.__name__) ) res.open(access_mode, open_timeout) for key, value in kwargs.items(): setattr(res, key, value) self._created_resources.add(res) return res def get_instrument( self, resource_name: str, access_mode: constants.AccessModes = constants.AccessModes.no_lock, open_timeout: int = constants.VI_TMO_IMMEDIATE, resource_pyclass: Type["Resource"] = None, **kwargs: Any, ) -> "Resource": """Return an instrument for the resource name. .. warning:: get_instrument is deprecated and will be removed in 1.12, use open_resource instead." Parameters ---------- resource_name : str Name or alias of the resource to open. access_mode : constants.AccessModes, optional Specifies the mode by which the resource is to be accessed, by default constants.AccessModes.no_lock open_timeout : int, optional If the ``access_mode`` parameter requests a lock, then this parameter specifies the absolute time period (in milliseconds) that the resource waits to get unlocked before this operation returns an error, by default constants.VI_TMO_IMMEDIATE. resource_pyclass : Optional[Type[Resource]], optional Resource Python class to use to instantiate the Resource. Defaults to None: select based on the resource name. kwargs : Any Keyword arguments to be used to change instrument attributes after construction. Returns ------- Resource Subclass of Resource matching the resource. """ warnings.warn( "get_instrument is deprecated and will be removed in " "1.12, use open_resource instead.", FutureWarning, ) return self.open_resource( resource_name, access_mode, open_timeout, resource_pyclass, **kwargs ) pyvisa-1.11.3/pyvisa/py.typed000066400000000000000000000000001375165327600161270ustar00rootroot00000000000000pyvisa-1.11.3/pyvisa/resources/000077500000000000000000000000001375165327600164545ustar00rootroot00000000000000pyvisa-1.11.3/pyvisa/resources/__init__.py000066400000000000000000000017561375165327600205760ustar00rootroot00000000000000# -*- coding: utf-8 -*- """High level wrappers for resources. This file is part of PyVISA. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ from .firewire import FirewireInstrument from .gpib import GPIBInstrument, GPIBInterface from .messagebased import MessageBasedResource from .pxi import PXIInstrument, PXIMemory from .registerbased import RegisterBasedResource from .resource import Resource from .serial import SerialInstrument from .tcpip import TCPIPInstrument, TCPIPSocket from .usb import USBInstrument, USBRaw from .vxi import VXIBackplane, VXIInstrument, VXIMemory __all__ = [ "Resource", "MessageBasedResource", "RegisterBasedResource", "GPIBInterface", "VXIBackplane", "VXIInstrument", "GPIBInstrument", "TCPIPInstrument", "TCPIPSocket", "SerialInstrument", "USBRaw", "USBInstrument", "FirewireInstrument", "PXIMemory", "PXIInstrument", "VXIMemory", ] pyvisa-1.11.3/pyvisa/resources/firewire.py000066400000000000000000000013261375165327600206440ustar00rootroot00000000000000# -*- coding: utf-8 -*- """High level wrapper for VXI resources. This file is part of PyVISA. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ from .. import constants from .registerbased import RegisterBasedResource @RegisterBasedResource.register(constants.InterfaceType.firewire, "INSTR") class FirewireInstrument(RegisterBasedResource): """Communicates with devices of type VXI::VXI logical address[::INSTR] More complex resource names can be specified with the following grammar: VXI[board]::VXI logical address[::INSTR] Do not instantiate directly, use :meth:`pyvisa.highlevel.ResourceManager.open_resource`. """ pyvisa-1.11.3/pyvisa/resources/gpib.py000066400000000000000000000215011375165327600177460ustar00rootroot00000000000000# -*- coding: utf-8 -*- """High level wrapper for GPIB resources. This file is part of PyVISA. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ import warnings from time import perf_counter from typing import Tuple from .. import attributes, constants from ..attributes import Attribute from .messagebased import ControlRenMixin, MessageBasedResource from .resource import Resource class _GPIBMixin(ControlRenMixin): """Common attributes and methods of GPIB Instr and Interface.""" #: Primary address of the GPIB device used by the given session. primary_address: Attribute[int] = attributes.AttrVI_ATTR_GPIB_PRIMARY_ADDR() #: Secondary address of the GPIB device used by the given session. secondary_address: Attribute[int] = attributes.AttrVI_ATTR_GPIB_SECONDARY_ADDR() #: Current state of the GPIB REN (Remote ENable) interface line. remote_enabled: Attribute[ constants.LineState ] = attributes.AttrVI_ATTR_GPIB_REN_STATE() def send_command(self, data: bytes) -> Tuple[int, constants.StatusCode]: """Write GPIB command bytes on the bus. Corresponds to viGpibCommand function of the VISA library. Parameters ---------- data : bytes Command to write. Returns ------- int Number of bytes written constants.StatusCode Return value of the library call. """ if not isinstance(self, GPIBInterface): warnings.warn( FutureWarning( "`send_command` is only supported on GPIB::INTFC resources " "and the methods will be removed in PyVISA 1.12" ) ) return self.visalib.gpib_command(self.session, data) def control_atn(self, mode: constants.ATNLineOperation) -> constants.StatusCode: """Specifies the state of the ATN line and the local active controller state. Corresponds to viGpibControlATN function of the VISA library. Parameters ---------- mode : constants.ATNLineOperation Specifies the state of the ATN line and optionally the local active controller state. Returns ------- constants.StatusCode Return value of the library call. """ if not isinstance(self, GPIBInterface): warnings.warn( FutureWarning( "`control_atn` is only supported on GPIB::INTFC resources " "and the methods will be removed in PyVISA 1.12" ) ) return self.visalib.gpib_control_atn(self.session, mode) def pass_control( self, primary_address: int, secondary_address: int ) -> constants.StatusCode: """Tell a GPIB device to become controller in charge (CIC). Corresponds to viGpibPassControl function of the VISA library. Parameters ---------- primary_address : int Primary address of the GPIB device to which you want to pass control. secondary_address : int Secondary address of the targeted GPIB device. If the targeted device does not have a secondary address, this parameter should contain the value Constants.NO_SEC_ADDR. Returns ------- constants.StatusCode Return value of the library call. """ if not isinstance(self, GPIBInterface): warnings.warn( FutureWarning( "`pass_control` is only supported on GPIB::INTFC resources " "and the methods will be removed in PyVISA 1.12" ) ) return self.visalib.gpib_pass_control( self.session, primary_address, secondary_address ) def send_ifc(self) -> constants.StatusCode: """Pulse the interface clear line (IFC) for at least 100 microseconds. Corresponds to viGpibSendIFC function of the VISA library. """ if not isinstance(self, GPIBInterface): warnings.warn( FutureWarning( "`send_ifc` is only supported on GPIB::INTFC resources " "and the methods will be removed in PyVISA 1.12" ) ) return self.visalib.gpib_send_ifc(self.session) @Resource.register(constants.InterfaceType.gpib, "INSTR") class GPIBInstrument(_GPIBMixin, MessageBasedResource): """Communicates with to devices of type GPIB::[::INSTR] More complex resource names can be specified with the following grammar: GPIB[board]::primary address[::secondary address][::INSTR] Do not instantiate directly, use :meth:`pyvisa.highlevel.ResourceManager.open_resource`. """ #: Whether to unaddress the device (UNT and UNL) after each read or write operation. enable_unaddressing: Attribute[bool] = attributes.AttrVI_ATTR_GPIB_UNADDR_EN() #: Whether to use repeat addressing before each read or write operation. enable_repeat_addressing: Attribute[bool] = attributes.AttrVI_ATTR_GPIB_READDR_EN() def wait_for_srq(self, timeout: int = 25000) -> None: """Wait for a serial request (SRQ) coming from the instrument. Note that this method is not ended when *another* instrument signals an SRQ, only *this* instrument. Parameters ---------- timeout : int Maximum waiting time in milliseconds. Defaul: 25000 (milliseconds). None means waiting forever if necessary. """ self.enable_event( constants.EventType.service_request, constants.EventMechanism.queue ) if timeout and not (0 <= timeout <= 4294967295): raise ValueError("timeout value is invalid") starting_time = perf_counter() while True: if timeout is None: adjusted_timeout = constants.VI_TMO_INFINITE else: adjusted_timeout = int( (starting_time + timeout / 1e3 - perf_counter()) * 1e3 ) if adjusted_timeout < 0: adjusted_timeout = 0 self.wait_on_event(constants.EventType.service_request, adjusted_timeout) if self.stb & 0x40: break self.discard_events( constants.EventType.service_request, constants.EventMechanism.queue ) @Resource.register(constants.InterfaceType.gpib, "INTFC") class GPIBInterface(_GPIBMixin, MessageBasedResource): """Communicates with to devices of type GPIB::INTFC More complex resource names can be specified with the following grammar: GPIB[board]::INTFC Do not instantiate directly, use :meth:`pyvisa.highlevel.ResourceManager.open_resource`. """ #: Is the specified GPIB interface currently the system controller. is_system_controller: Attribute[ bool ] = attributes.AttrVI_ATTR_GPIB_SYS_CNTRL_STATE() #: Is the specified GPIB interface currently CIC (Controller In Charge). is_controller_in_charge: Attribute[bool] = attributes.AttrVI_ATTR_GPIB_CIC_STATE() #: Current state of the GPIB ATN (ATtentioN) interface line. atn_state: Attribute[constants.LineState] = attributes.AttrVI_ATTR_GPIB_ATN_STATE() #: Current state of the GPIB NDAC (Not Data ACcepted) interface line. ndac_state: Attribute[ constants.LineState ] = attributes.AttrVI_ATTR_GPIB_NDAC_STATE() #: Is the GPIB interface currently addressed to talk or listen, or is not addressed. address_state: Attribute[ constants.LineState ] = attributes.AttrVI_ATTR_GPIB_ADDR_STATE() def group_execute_trigger( self, *resources: GPIBInstrument ) -> Tuple[int, constants.StatusCode]: """ Parameters ---------- resources : GPIBInstrument GPIB resources to which to send the group trigger. Returns ------- int Number of bytes written as part of sending the GPIB commands. constants.StatusCode Return value of the library call. """ for resource in resources: if not isinstance(resource, GPIBInstrument): raise ValueError("%r is not a GPIBInstrument", resource) # TODO: check that all resources are in the same board. if not self.is_controller_in_charge: self.send_ifc() command = [ 0x40, 0x20 + 31, ] # broadcast TAD#0 and "UNL" (don't listen) to all devices for resource in resources: # tell device GPIB::11 to listen command.append(0x20 + resource.primary_address) # send GET ('group execute trigger') command.append(0x08) return self.send_command(bytes(command)) pyvisa-1.11.3/pyvisa/resources/messagebased.py000066400000000000000000000667631375165327600214730ustar00rootroot00000000000000# -*- coding: utf-8 -*- """High level wrapper for MessageBased Instruments. This file is part of PyVISA. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ import contextlib import struct import time import warnings from typing import Any, Callable, Iterable, Iterator, Optional, Sequence, Type, Union from .. import attributes, constants, errors, logger, util from ..attributes import Attribute from ..highlevel import VisaLibraryBase from .resource import Resource class ControlRenMixin(object): """Common control_ren method of some messaged based resources. """ #: Will be present when used as a mixin with Resource visalib: VisaLibraryBase #: Will be present when used as a mixin with Resource session: Any # It should work for GPIB, USB and some TCPIP # For TCPIP I found some (all?) NI's VISA library do not handle # control_ren, but it works for Agilent's VISA library (at least some of # them) def control_ren(self, mode: constants.RENLineOperation) -> constants.StatusCode: """Controls the state of the GPIB Remote Enable (REN) interface line. The remote/local state of the device can also be controlled optionally. Corresponds to viGpibControlREN function of the VISA library. Parameters ---------- mode : constants.RENLineOperation Specifies the state of the REN line and optionally the device remote/local state. Returns ------- constants.StatusCode Return value of the library call. """ return self.visalib.gpib_control_ren(self.session, mode) class MessageBasedResource(Resource): """Base class for resources that use message based communication.""" CR: str = "\r" LF: str = "\n" #: Number of bytes to read at a time. Some resources (serial) may not support #: large chunk sizes. chunk_size: int = 20 * 1024 #: Delay in s to sleep between the write and read occuring in a query query_delay: float = 0.0 #: Internal storage for the read_termination character _read_termination: Optional[str] = None #: Internal storage for the write_termination character _write_termination: str = CR + LF #: Internal storage for the encoding _encoding: str = "ascii" @property def encoding(self) -> str: """Encoding used for read and write operations.""" return self._encoding @encoding.setter def encoding(self, encoding: str) -> None: # Test that the encoding specified makes sense. "test encoding".encode(encoding).decode(encoding) self._encoding = encoding @property def read_termination(self) -> Optional[str]: """Read termination character.""" return self._read_termination @read_termination.setter def read_termination(self, value: str) -> None: if value: # termination character, the rest is just used for verification # after each read operation. last_char = value[-1:] # Consequently, it's illogical to have the real termination # character twice in the sequence (otherwise reading would stop # prematurely). if last_char in value[:-1]: raise ValueError("ambiguous ending in termination characters") self.set_visa_attribute( constants.ResourceAttribute.termchar, ord(last_char) ) self.set_visa_attribute( constants.ResourceAttribute.termchar_enabled, constants.VI_TRUE ) else: # The termchar is also used in VI_ATTR_ASRL_END_IN (for serial # termination) so return it to its default. self.set_visa_attribute(constants.ResourceAttribute.termchar, ord(self.LF)) self.set_visa_attribute( constants.ResourceAttribute.termchar_enabled, constants.VI_FALSE ) self._read_termination = value @property def write_termination(self) -> str: """Write termination character.""" return self._write_termination @write_termination.setter def write_termination(self, value: str) -> None: self._write_termination = value #: Should END be asserted during the transfer of the last byte of the buffer. send_end: Attribute[bool] = attributes.AttrVI_ATTR_SEND_END_EN() #: IO protocol to use. See the attribute definition for more details. io_protocol: Attribute[constants.IOProtocol] = attributes.AttrVI_ATTR_IO_PROT() #: Should I/O accesses use DMA (True) or Programmed I/O (False). allow_dma: Attribute[bool] = attributes.AttrVI_ATTR_DMA_ALLOW_EN() def write_raw(self, message: bytes) -> int: """Write a byte message to the device. Parameters ---------- message : bytes The message to be sent. Returns ------- int Number of bytes written """ return self.visalib.write(self.session, message)[0] def write( self, message: str, termination: Optional[str] = None, encoding: Optional[str] = None, ) -> int: """Write a string message to the device. The write_termination is always appended to it. Parameters ---------- message : str The message to be sent. termination : Optional[str], optional Alternative character termination to use. If None, the value of write_termination is used. Defaults to None. encoding : Optional[str], optional Alternative encoding to use to turn str into bytes. If None, the value of encoding is used. Defaults to None. Returns ------- int Number of bytes written. """ term = self._write_termination if termination is None else termination enco = self._encoding if encoding is None else encoding if term: if message.endswith(term): warnings.warn( "write message already ends with " "termination characters", stacklevel=2, ) message += term count = self.write_raw(message.encode(enco)) return count def write_ascii_values( self, message: str, values: Sequence[Any], converter: util.ASCII_CONVERTER = "f", separator: Union[str, Callable[[Iterable[str]], str]] = ",", termination: Optional[str] = None, encoding: Optional[str] = None, ): """Write a string message to the device followed by values in ascii format. The write_termination is always appended to it. Parameters ---------- message : str Header of the message to be sent. values : Sequence[Any] Data to be writen to the device. converter : Union[str, Callable[[Any], str]], optional Str formatting codes or function used to convert each value. Defaults to "f". separator : Union[str, Callable[[Iterable[str]], str]], optional Str or callable that join the values in a single str. If a str is given, separator.join(values) is used. Defaults to ',' termination : Optional[str], optional Alternative character termination to use. If None, the value of write_termination is used. Defaults to None. encoding : Optional[str], optional Alternative encoding to use to turn str into bytes. If None, the value of encoding is used. Defaults to None. Returns ------- int Number of bytes written. """ term = self._write_termination if termination is None else termination enco = self._encoding if encoding is None else encoding if term and message.endswith(term): warnings.warn( "write message already ends with " "termination characters", stacklevel=2, ) block = util.to_ascii_block(values, converter, separator) msg = message.encode(enco) + block.encode(enco) if term: msg += term.encode(enco) count = self.write_raw(msg) return count def write_binary_values( self, message: str, values: Sequence[Any], datatype: util.BINARY_DATATYPES = "f", is_big_endian: bool = False, termination: Optional[str] = None, encoding: Optional[str] = None, header_fmt: util.BINARY_HEADERS = "ieee", ): """Write a string message to the device followed by values in binary format. The write_termination is always appended to it. Parameters ---------- message : str The header of the message to be sent. values : Sequence[Any] Data to be written to the device. datatype : util.BINARY_DATATYPES, optional The format string for a single element. See struct module. is_big_endian : bool, optional Are the data in big or little endian order. termination : Optional[str], optional Alternative character termination to use. If None, the value of write_termination is used. Defaults to None. encoding : Optional[str], optional Alternative encoding to use to turn str into bytes. If None, the value of encoding is used. Defaults to None. header_fmt : util.BINARY_HEADERS Format of the header prefixing the data. Returns ------- int Number of bytes written. """ term = self._write_termination if termination is None else termination enco = self._encoding if encoding is None else encoding if term and message.endswith(term): warnings.warn( "write message already ends with " "termination characters", stacklevel=2, ) if header_fmt == "ieee": block = util.to_ieee_block(values, datatype, is_big_endian) elif header_fmt == "hp": block = util.to_hp_block(values, datatype, is_big_endian) elif header_fmt == "empty": block = util.to_binary_block(values, b"", datatype, is_big_endian) else: raise ValueError("Unsupported header_fmt: %s" % header_fmt) msg = message.encode(enco) + block if term: msg += term.encode(enco) count = self.write_raw(msg) return count def read_bytes( self, count: int, chunk_size: Optional[int] = None, break_on_termchar: bool = False, ) -> bytes: """Read a certain number of bytes from the instrument. Parameters ---------- count : int The number of bytes to read from the instrument. chunk_size : Optional[int], optional The chunk size to use to perform the reading. If count > chunk_size multiple low level operations will be performed. Defaults to None, meaning the resource wide set value is set. break_on_termchar : bool, optional Should the reading stop when a termination character is encountered or when the message ends. Defaults to False. Returns ------- bytes Bytes read from the instrument. """ chunk_size = chunk_size or self.chunk_size ret = bytearray() left_to_read = count success = constants.StatusCode.success termchar_read = constants.StatusCode.success_termination_character_read with self.ignore_warning( constants.StatusCode.success_device_not_present, constants.StatusCode.success_max_count_read, ): try: status = None while len(ret) < count: size = min(chunk_size, left_to_read) logger.debug( "%s - reading %d bytes (last status %r)", self._resource_name, size, status, ) chunk, status = self.visalib.read(self.session, size) ret.extend(chunk) left_to_read -= len(chunk) if break_on_termchar and ( status == success or status == termchar_read ): break except errors.VisaIOError as e: logger.debug( "%s - exception while reading: %s\n" "Buffer content: %r", self._resource_name, e, ret, ) raise return bytes(ret) def read_raw(self, size: Optional[int] = None) -> bytes: """Read the unmodified string sent from the instrument to the computer. In contrast to read(), no termination characters are stripped. Parameters ---------- size : Optional[int], optional The chunk size to use to perform the reading. Defaults to None, meaning the resource wide set value is set. Returns ------- bytes Bytes read from the instrument. """ return bytes(self._read_raw(size)) def _read_raw(self, size: Optional[int] = None): """Read the unmodified string sent from the instrument to the computer. In contrast to read(), no termination characters are stripped. Parameters ---------- size : Optional[int], optional The chunk size to use to perform the reading. Defaults to None, meaning the resource wide set value is set. Returns ------- bytearray Bytes read from the instrument. """ size = self.chunk_size if size is None else size loop_status = constants.StatusCode.success_max_count_read ret = bytearray() with self.ignore_warning( constants.StatusCode.success_device_not_present, constants.StatusCode.success_max_count_read, ): try: status = loop_status while status == loop_status: logger.debug( "%s - reading %d bytes (last status %r)", self._resource_name, size, status, ) chunk, status = self.visalib.read(self.session, size) ret.extend(chunk) except errors.VisaIOError as e: logger.debug( "%s - exception while reading: %s\nBuffer " "content: %r", self._resource_name, e, ret, ) raise return ret def read( self, termination: Optional[str] = None, encoding: Optional[str] = None ) -> str: """Read a string from the device. Reading stops when the device stops sending (e.g. by setting appropriate bus lines), or the termination characters sequence was detected. Attention: Only the last character of the termination characters is really used to stop reading, however, the whole sequence is compared to the ending of the read string message. If they don't match, a warning is issued. Parameters ---------- termination : Optional[str], optional Alternative character termination to use. If None, the value of write_termination is used. Defaults to None. encoding : Optional[str], optional Alternative encoding to use to turn bytes into str. If None, the value of encoding is used. Defaults to None. Returns ------- str Message read from the instrument and decoded. """ enco = self._encoding if encoding is None else encoding if termination is None: termination = self._read_termination message = self._read_raw().decode(enco) else: with self.read_termination_context(termination): message = self._read_raw().decode(enco) if not termination: return message if not message.endswith(termination): warnings.warn( "read string doesn't end with " "termination characters", stacklevel=2 ) return message return message[: -len(termination)] def read_ascii_values( self, converter: util.ASCII_CONVERTER = "f", separator: Union[str, Callable[[str], Iterable[str]]] = ",", container: Union[Type, Callable[[Iterable], Sequence]] = list, ) -> Sequence: """Read values from the device in ascii format returning an iterable of values. Parameters ---------- converter : ASCII_CONVERTER, optional Str format of function to convert each value. Default to "f". separator : Union[str, Callable[[str], Iterable[str]]] str or callable used to split the data into individual elements. If a str is given, data.split(separator) is used. Default to ",". container : Union[Type, Callable[[Iterable], Sequence]], optional Container type to use for the output data. Possible values are: list, tuple, np.ndarray, etc, Default to list. Returns ------- Sequence Parsed data. """ # Use read rather than _read_raw because we cannot handle a bytearray block = self.read() return util.from_ascii_block(block, converter, separator, container) def read_binary_values( self, datatype: util.BINARY_DATATYPES = "f", is_big_endian: bool = False, container: Union[Type, Callable[[Iterable], Sequence]] = list, header_fmt: util.BINARY_HEADERS = "ieee", expect_termination: bool = True, data_points: int = 0, chunk_size: Optional[int] = None, ) -> Sequence[Union[int, float]]: """Read values from the device in binary format returning an iterable of values. Parameters ---------- datatype : BINARY_DATATYPES, optional Format string for a single element. See struct module. 'f' by default. is_big_endian : bool, optional Are the data in big or little endian order. Defaults to False. container : Union[Type, Callable[[Iterable], Sequence]], optional Container type to use for the output data. Possible values are: list, tuple, np.ndarray, etc, Default to list. header_fmt : util.BINARY_HEADERS, optional Format of the header prefixing the data. Defaults to 'ieee'. expect_termination : bool, optional When set to False, the expected length of the binary values block does not account for the final termination character (the read termination). Defaults to True. data_points : int, optional Number of points expected in the block. This is used only if the instrument does not report it itself. This will be converted in a number of bytes based on the datatype. Defaults to 0. chunk_size : int, optional Size of the chunks to read from the device. Using larger chunks may be faster for large amount of data. Returns ------- Sequence[Union[int, float]] Data read from the device. """ block = self._read_raw(chunk_size) if header_fmt == "ieee": offset, data_length = util.parse_ieee_block_header(block) elif header_fmt == "hp": offset, data_length = util.parse_hp_block_header(block, is_big_endian) elif header_fmt == "empty": offset = 0 data_length = 0 else: raise ValueError( "Invalid header format. Valid options are 'ieee'," " 'empty', 'hp'" ) # Allow to support instrument such as the Keithley 2000 that do not # report the length of the block data_length = data_length or data_points * struct.calcsize(datatype) expected_length = offset + data_length if expect_termination and self._read_termination is not None: expected_length += len(self._read_termination) # Read all the data if we know what to expect. if data_length != 0: block.extend( self.read_bytes(expected_length - len(block), chunk_size=chunk_size) ) else: raise ValueError( "The length of the data to receive could not be " "determined. You should provide the number of " "points you expect using the data_points keyword " "argument." ) try: # Do not reparse the headers since it was already done and since # this allows for custom data length return util.from_binary_block( block, offset, data_length, datatype, is_big_endian, container ) except ValueError as e: raise errors.InvalidBinaryFormat(e.args[0]) def query(self, message: str, delay: Optional[float] = None) -> str: """A combination of write(message) and read() Parameters ---------- message : str The message to send. delay : Optional[float], optional Delay in seconds between write and read operations. If None, defaults to self.query_delay. Returns ------- str Answer from the device. """ self.write(message) delay = self.query_delay if delay is None else delay if delay > 0.0: time.sleep(delay) return self.read() def query_ascii_values( self, message: str, converter: util.ASCII_CONVERTER = "f", separator: Union[str, Callable[[str], Iterable[str]]] = ",", container: Union[Type, Callable[[Iterable], Sequence]] = list, delay: Optional[float] = None, ) -> Sequence[Any]: """Query the device for values in ascii format returning an iterable of values. Parameters ---------- message : str The message to send. converter : ASCII_CONVERTER, optional Str format of function to convert each value. Default to "f". separator : Union[str, Callable[[str], Iterable[str]]] str or callable used to split the data into individual elements. If a str is given, data.split(separator) is used. Default to ",". container : Union[Type, Callable[[Iterable], Sequence]], optional Container type to use for the output data. Possible values are: list, tuple, np.ndarray, etc, Default to list. delay : Optional[float], optional Delay in seconds between write and read operations. If None, defaults to self.query_delay. Returns ------- Sequence Parsed data. """ self.write(message) if delay is None: delay = self.query_delay if delay > 0.0: time.sleep(delay) return self.read_ascii_values(converter, separator, container) def query_binary_values( self, message: str, datatype: util.BINARY_DATATYPES = "f", is_big_endian: bool = False, container: Union[Type, Callable[[Iterable], Sequence]] = list, delay: Optional[float] = None, header_fmt: util.BINARY_HEADERS = "ieee", expect_termination: bool = True, data_points: int = 0, chunk_size: Optional[int] = None, ) -> Sequence[Union[int, float]]: """Query the device for values in binary format returning an iterable of values. Parameters ---------- message : str The message to send. datatype : BINARY_DATATYPES, optional Format string for a single element. See struct module. 'f' by default. is_big_endian : bool, optional Are the data in big or little endian order. Defaults to False. container : Union[Type, Callable[[Iterable], Sequence]], optional Container type to use for the output data. Possible values are: list, tuple, np.ndarray, etc, Default to list. delay : Optional[float], optional Delay in seconds between write and read operations. If None, defaults to self.query_delay. header_fmt : util.BINARY_HEADERS, optional Format of the header prefixing the data. Defaults to 'ieee'. expect_termination : bool, optional When set to False, the expected length of the binary values block does not account for the final termination character (the read termination). Defaults to True. data_points : int, optional Number of points expected in the block. This is used only if the instrument does not report it itself. This will be converted in a number of bytes based on the datatype. Defaults to 0. chunk_size : int, optional Size of the chunks to read from the device. Using larger chunks may be faster for large amount of data. Returns ------- Sequence[Union[int, float]] Data read from the device. """ if header_fmt not in ("ieee", "empty", "hp"): raise ValueError( "Invalid header format. Valid options are 'ieee'," " 'empty', 'hp'" ) self.write(message) if delay is None: delay = self.query_delay if delay > 0.0: time.sleep(delay) return self.read_binary_values( datatype, is_big_endian, container, header_fmt, expect_termination, data_points, chunk_size, ) def assert_trigger(self) -> None: """Sends a software trigger to the device.""" self.visalib.assert_trigger(self.session, constants.TriggerProtocol.default) @property def stb(self) -> int: """Service request status register.""" return self.read_stb() def read_stb(self) -> int: """Service request status register.""" value, retcode = self.visalib.read_stb(self.session) return value @contextlib.contextmanager def read_termination_context(self, new_termination: str) -> Iterator: term = self.get_visa_attribute(constants.ResourceAttribute.termchar) self.set_visa_attribute( constants.ResourceAttribute.termchar, ord(new_termination[-1]) ) yield self.set_visa_attribute(constants.ResourceAttribute.termchar, term) def flush(self, mask: constants.BufferOperation) -> None: """Manually clears the specified buffers. Depending on the value of the mask this can cause the buffer data to be written to the device. Parameters ---------- mask : constants.BufferOperation Specifies the action to be taken with flushing the buffer. See highlevel.VisaLibraryBase.flush for a detailed description. """ self.visalib.flush(self.session, mask) # Rohde and Schwarz Device via Passport. Not sure which Resource should be. MessageBasedResource.register(constants.InterfaceType.rsnrp, "INSTR")( MessageBasedResource ) pyvisa-1.11.3/pyvisa/resources/pxi.py000066400000000000000000000052031375165327600176260ustar00rootroot00000000000000# -*- coding: utf-8 -*- """High level wrapper for pxi resources. This file is part of PyVISA. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ from .. import attributes, constants from ..attributes import Attribute from .registerbased import RegisterBasedResource from .resource import Resource @Resource.register(constants.InterfaceType.pxi, "BACKPLANE") class PXIBackplane(RegisterBasedResource): """Communicates with to devices of type PXI[interface]::BACKPLANE Do not instantiate directly, use :meth:`pyvisa.highlevel.ResourceManager.open_resource`. """ #: Manufacturer name. manufacturer_name: Attribute[str] = attributes.AttrVI_ATTR_MANF_NAME() #: Model name of the device. model_name: Attribute[str] = attributes.AttrVI_ATTR_MODEL_NAME() class PXICommon(RegisterBasedResource): """Common parent class for PXI INSTR and MEMACC resources.""" #: Number of elements by which to increment the source offset after a transfer. source_increment: Attribute[int] = attributes.AttrVI_ATTR_SRC_INCREMENT() #: Number of elements by which to increment the destination offset after a transfer. destination_increment: Attribute[int] = attributes.AttrVI_ATTR_DEST_INCREMENT() #: Should I/O accesses use DMA (True) or Programmed I/O (False). allow_dma: Attribute[bool] = attributes.AttrVI_ATTR_DMA_ALLOW_EN() @Resource.register(constants.InterfaceType.pxi, "INSTR") class PXIInstrument(PXICommon): """Communicates with to devices of type PXI::[::INSTR] More complex resource names can be specified with the following grammar: PXI[bus]::device[::function][::INSTR] or: PXI[interface]::bus-device[.function][::INSTR] or: PXI[interface]::CHASSISchassis number::SLOTslot number[::FUNCfunction][::INSTR] Do not instantiate directly, use :meth:`pyvisa.highlevel.ResourceManager.open_resource`. """ #: Manufacturer name. manufacturer_name: Attribute[str] = attributes.AttrVI_ATTR_MANF_NAME() #: Manufacturer identification number of the device. manufacturer_id: Attribute[int] = attributes.AttrVI_ATTR_MANF_ID() #: Model name of the device. model_name: Attribute[str] = attributes.AttrVI_ATTR_MODEL_NAME() #: Model code for the device. model_code: Attribute[int] = attributes.AttrVI_ATTR_MODEL_CODE() @Resource.register(constants.InterfaceType.pxi, "MEMACC") class PXIMemory(PXICommon): """Communicates with to devices of type PXI[interface]::MEMACC Do not instantiate directly, use :meth:`pyvisa.highlevel.ResourceManager.open_resource`. """ pyvisa-1.11.3/pyvisa/resources/registerbased.py000066400000000000000000000123341375165327600216540ustar00rootroot00000000000000# -*- coding: utf-8 -*- """High level wrapper for RegisterBased Instruments. This file is part of PyVISA. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ from typing import Iterable, List from .. import constants from .resource import Resource class RegisterBasedResource(Resource): """Base class for resources that use register based communication.""" def read_memory( self, space: constants.AddressSpace, offset: int, width: constants.DataWidth, extended: bool = False, ) -> int: """Read a value from the specified memory space and offset. Parameters ---------- space : constants.AddressSpace Specifies the address space from which to read. offset : int Offset (in bytes) of the address or register from which to read. width : Union[Literal[8, 16, 32, 64], constants.DataWidth] Number of bits to read (8, 16, 32 or 64). extended : bool, optional Use 64 bits offset independent of the platform. Returns ------- data : int Data read from memory Raises ------ ValueError Raised if an invalid width is specified. """ return self.visalib.read_memory(self.session, space, offset, width, extended)[0] def write_memory( self, space: constants.AddressSpace, offset: int, data: int, width: constants.DataWidth, extended: bool = False, ) -> constants.StatusCode: """Write a value to the specified memory space and offset. Parameters ---------- space : constants.AddressSpace Specifies the address space. offset : int Offset (in bytes) of the address or register from which to read. data : int Data to write to bus. width : Union[Literal[8, 16, 32, 64], constants.DataWidth] Number of bits to read. extended : bool, optional Use 64 bits offset independent of the platform, by default False. Returns ------- constants.StatusCode Return value of the library call. Raises ------ ValueError Raised if an invalid width is specified. """ return self.visalib.write_memory( self.session, space, offset, data, width, extended ) def move_in( self, space: constants.AddressSpace, offset: int, length: int, width: constants.DataWidth, extended: bool = False, ) -> List[int]: """Move a block of data to local memory from the given address space and offset. Corresponds to viMoveIn* functions of the VISA library. Parameters ---------- space : constants.AddressSpace Address space from which to move the data. offset : int Offset (in bytes) of the address or register from which to read. length : int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. width : Union[Literal[8, 16, 32, 64], constants.DataWidth] Number of bits to read per element. extended : bool, optional Use 64 bits offset independent of the platform, by default False. Returns ------- data : List[int] Data read from the bus status_code : constants.StatusCode Return value of the library call. Raises ------ ValueError Raised if an invalid width is specified. """ return self.visalib.move_in( self.session, space, offset, length, width, extended )[0] def move_out( self, space: constants.AddressSpace, offset: int, length: int, data: Iterable[int], width: constants.DataWidth, extended: bool = False, ) -> constants.StatusCode: """Move a block of data from local memory to the given address space and offset. Corresponds to viMoveOut* functions of the VISA library. Parameters ---------- space : constants.AddressSpace Address space into which move the data. offset : int Offset (in bytes) of the address or register from which to read. length : int Number of elements to transfer, where the data width of the elements to transfer is identical to the source data width. data : Iterable[int] Data to write to bus. width : Union[Literal[8, 16, 32, 64], constants.DataWidth] Number of bits to per element. extended : bool, optional Use 64 bits offset independent of the platform, by default False. Returns ------- constants.StatusCode Return value of the library call. Raises ------ ValueError Raised if an invalid width is specified. """ return self.visalib.move_out( self.session, space, offset, length, data, width, extended ) pyvisa-1.11.3/pyvisa/resources/resource.py000066400000000000000000000543611375165327600206660ustar00rootroot00000000000000# -*- coding: utf-8 -*- """High level wrapper for a Resource. This file is part of PyVISA. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ import contextlib import time import warnings from functools import update_wrapper from typing import ( Any, Callable, ContextManager, Iterator, Optional, Set, Type, TypeVar, Union, cast, ) from typing_extensions import ClassVar, Literal from .. import attributes, constants, errors, highlevel, logger, rname, typing, util from ..attributes import Attribute from ..events import Event from ..typing import VISAEventContext, VISAHandler, VISASession class WaitResponse: """Class used in return of wait_on_event. It properly closes the context upon delete. A call with event_type of 0 (normally used when timed_out is True) will store None as the event and event type, otherwise it records the proper Event. """ #: Reference to the event object that was waited for. event: Event #: Status code returned by the VISA library ret: constants.StatusCode #: Did a timeout occurs timed_out: bool def __init__( self, event_type: constants.EventType, context: Optional[VISAEventContext], ret: constants.StatusCode, visalib: highlevel.VisaLibraryBase, timed_out: bool = False, ): self.event = Event(visalib, event_type, context) self._event_type = constants.EventType(event_type) self._context = context self.ret = ret self._visalib = visalib self.timed_out = timed_out @property def event_type(self) -> Optional[constants.EventType]: warnings.warn( "event_type is deprecated and will be removed in 1.12. " "Use the event object instead.", FutureWarning, ) return self._event_type @property def context(self) -> Optional[VISAEventContext]: warnings.warn( "context is deprecated and will be removed in 1.12. " "Use the event object instead to access the event attributes.", FutureWarning, ) return self._context def __del__(self) -> None: if self.event._context is not None: try: self._visalib.close(self.event._context) self.event.close() except errors.VisaIOError: pass T = TypeVar("T", bound="Resource") class Resource(object): """Base class for resources. Do not instantiate directly, use :meth:`pyvisa.highlevel.ResourceManager.open_resource`. """ #: Reference to the resource manager used by this resource resource_manager: highlevel.ResourceManager #: Reference to the VISA library instance used by the resource visalib: highlevel.VisaLibraryBase #: VISA attribute descriptor classes that can be used to introspect the #: supported attributes and the possible values. The "often used" ones #: are generally directly available on the resource. visa_attributes_classes: ClassVar[Set[Type[attributes.Attribute]]] @classmethod def register( cls, interface_type: constants.InterfaceType, resource_class: str ) -> Callable[[Type[T]], Type[T]]: """Create a decorator to register a class. The class is associated to an interface type, resource class pair. Parameters ---------- interface_type : constants.InterfaceType Interface type for which to register a wrapper class. resource_class : str Resource class for which to register a wrapper class. Returns ------- Callable[[Type[T]], Type[T]] Decorator registering the class. Raises TypeError if some VISA attributes are missing on the registered class. """ def _internal(python_class): highlevel.ResourceManager.register_resource_class( interface_type, resource_class, python_class ) return python_class return _internal def __init__( self, resource_manager: highlevel.ResourceManager, resource_name: str ) -> None: self._resource_manager = resource_manager self.visalib = self._resource_manager.visalib # We store the resource name and use preferably the private attr over # the public descriptor internally because the public descriptor # requires a live instance the VISA library, which means it is much # slower but also can cause issue in error reporting when accessing the # repr self._resource_name: str try: # Attempt to normalize the resource name. Can fail for aliases self._resource_name = str(rname.ResourceName.from_string(resource_name)) except rname.InvalidResourceName: self._resource_name = resource_name self._logging_extra = { "library_path": self.visalib.library_path, "resource_manager.session": self._resource_manager.session, "resource_name": self._resource_name, "session": None, } #: Session handle. self._session: Optional[VISASession] = None @property def session(self) -> VISASession: """Resource session handle. Raises ------ errors.InvalidSession Raised if session is closed. """ if self._session is None: raise errors.InvalidSession() return self._session @session.setter def session(self, value: Optional[VISASession]) -> None: self._session = value def __del__(self) -> None: if self._session is not None: self.close() def __str__(self) -> str: return "%s at %s" % (self.__class__.__name__, self._resource_name) def __repr__(self) -> str: return "<%r(%r)>" % (self.__class__.__name__, self._resource_name) def __enter__(self) -> "Resource": return self def __exit__(self, *args) -> None: self.close() @property def last_status(self) -> constants.StatusCode: """Last status code for this session.""" return self.visalib.get_last_status_in_session(self.session) @property def resource_info(self) -> highlevel.ResourceInfo: """Get the extended information of this resource.""" return self.visalib.parse_resource_extended( self._resource_manager.session, self._resource_name )[0] # --- VISA attributes -------------------------------------------------------------- #: VISA attributes require the resource to be opened in order to get accessed. #: Please have a look at the attributes definition for more details #: Interface type of the given session. interface_type: Attribute[ constants.InterfaceType ] = attributes.AttrVI_ATTR_INTF_TYPE() #: Board number for the given interface. interface_number: Attribute[int] = attributes.AttrVI_ATTR_INTF_NUM() #: Resource class (for example, "INSTR") as defined by the canonical resource name. resource_class: Attribute[str] = attributes.AttrVI_ATTR_RSRC_CLASS() #: Unique identifier for a resource compliant with the address structure. resource_name: Attribute[str] = attributes.AttrVI_ATTR_RSRC_NAME() #: Resource version that identifies the revisions or implementations of a resource. implementation_version: Attribute[int] = attributes.AttrVI_ATTR_RSRC_IMPL_VERSION() #: Current locking state of the resource. lock_state: Attribute[ constants.AccessModes ] = attributes.AttrVI_ATTR_RSRC_LOCK_STATE() #: Version of the VISA specification to which the implementation is compliant. spec_version: Attribute[int] = attributes.AttrVI_ATTR_RSRC_SPEC_VERSION() #: Manufacturer name of the vendor that implemented the VISA library. resource_manufacturer_name: Attribute[str] = attributes.AttrVI_ATTR_RSRC_MANF_NAME() #: Timeout in milliseconds for all resource I/O operations. timeout: Attribute[float] = attributes.AttrVI_ATTR_TMO_VALUE() def ignore_warning( self, *warnings_constants: constants.StatusCode ) -> ContextManager: """Ignoring warnings context manager for the current resource. Parameters ---------- warnings_constants : constants.StatusCode Constants identifying the warnings to ignore. """ return self.visalib.ignore_warning(self.session, *warnings_constants) def open( self, access_mode: constants.AccessModes = constants.AccessModes.no_lock, open_timeout: int = 5000, ) -> None: """Opens a session to the specified resource. Parameters ---------- access_mode : constants.AccessModes, optional Specifies the mode by which the resource is to be accessed. Defaults to constants.AccessModes.no_lock. open_timeout : int, optional If the ``access_mode`` parameter requests a lock, then this parameter specifies the absolute time period (in milliseconds) that the resource waits to get unlocked before this operation returns an error. Defaults to 5000. """ logger.debug("%s - opening ...", self._resource_name, extra=self._logging_extra) with self._resource_manager.ignore_warning( constants.StatusCode.success_device_not_present ): self.session, status = self._resource_manager.open_bare_resource( self._resource_name, access_mode, open_timeout ) if status == constants.StatusCode.success_device_not_present: # The device was not ready when we opened the session. # Now it gets five seconds more to become ready. # Every 0.1 seconds we probe it with viClear. start_time = time.time() sleep_time = 0.1 try_time = 5 while time.time() - start_time < try_time: time.sleep(sleep_time) try: self.clear() break except errors.VisaIOError as error: if error.error_code != constants.StatusCode.error_no_listeners: raise self._logging_extra["session"] = self.session logger.debug( "%s - is open with session %s", self._resource_name, self.session, extra=self._logging_extra, ) def before_close(self) -> None: """Called just before closing an instrument.""" self.__switch_events_off() def close(self) -> None: """Closes the VISA session and marks the handle as invalid.""" try: logger.debug("%s - closing", self._resource_name, extra=self._logging_extra) self.before_close() self.visalib.close(self.session) logger.debug( "%s - is closed", self._resource_name, extra=self._logging_extra ) # Mypy is confused by the idea that we can set a value we cannot get self.session = None # type: ignore except errors.InvalidSession: pass def __switch_events_off(self) -> None: """Switch off and discrads all events.""" self.disable_event( constants.EventType.all_enabled, constants.EventMechanism.all ) self.discard_events( constants.EventType.all_enabled, constants.EventMechanism.all ) self.visalib.uninstall_all_visa_handlers(self.session) def get_visa_attribute(self, name: constants.ResourceAttribute) -> Any: """Retrieves the state of an attribute in this resource. One should prefer the dedicated descriptor for often used attributes since those perform checks and automatic conversion on the value. Parameters ---------- name : constants.ResourceAttribute Resource attribute for which the state query is made. Returns ------- Any The state of the queried attribute for a specified resource. """ return self.visalib.get_attribute(self.session, name)[0] def set_visa_attribute( self, name: constants.ResourceAttribute, state: Any ) -> constants.StatusCode: """Set the state of an attribute. One should prefer the dedicated descriptor for often used attributes since those perform checks and automatic conversion on the value. Parameters ---------- name : constants.ResourceAttribute Attribute for which the state is to be modified. state : Any The state of the attribute to be set for the specified object. Returns ------- constants.StatusCode Return value of the library call. """ return self.visalib.set_attribute(self.session, name, state) def clear(self) -> None: """Clear this resource.""" self.visalib.clear(self.session) def install_handler( self, event_type: constants.EventType, handler: VISAHandler, user_handle=None ) -> Any: """Install handlers for event callbacks in this resource. Parameters ---------- event_type : constants.EventType Logical event identifier. handler : VISAHandler Handler function to be installed by a client application. user_handle : A value specified by an application that can be used for identifying handlers uniquely for an event type. Depending on the backend they may be restriction on the possible values. Look at the backend `install_visa_handler` for more details. Returns ------- Any User handle in a format amenable to the backend. This is this representation of the handle that should be used when unistalling a handler. """ return self.visalib.install_visa_handler( self.session, event_type, handler, user_handle ) def wrap_handler( self, callable: Callable[["Resource", Event, Any], None] ) -> VISAHandler: """Wrap an event handler to provide the signature expected by VISA. The handler is expected to have the following signature: handler(resource: Resource, event: Event, user_handle: Any) -> None. The wrapped handler should be used only to handle events on the resource used to wrap the handler. """ def event_handler( session: VISASession, event_type: constants.EventType, event_context: typing.VISAEventContext, user_handle: Any, ) -> None: if session != self.session: raise RuntimeError( "When wrapping a handler, the resource used to wrap the handler" "must be the same on which the handler will be installed." f"Wrapping session: {self.session}, event on session: {session}" ) event = Event(self.visalib, event_type, event_context) try: return callable(self, event, user_handle) finally: event.close() update_wrapper(event_handler, callable) return event_handler def uninstall_handler( self, event_type: constants.EventType, handler: VISAHandler, user_handle=None ) -> None: """Uninstalls handlers for events in this resource. Parameters ---------- event_type : constants.EventType Logical event identifier. handler : VISAHandler Handler function to be uninstalled by a client application. user_handle : Any The user handle returned by install_handler. """ self.visalib.uninstall_visa_handler( self.session, event_type, handler, user_handle ) def disable_event( self, event_type: constants.EventType, mechanism: constants.EventMechanism ) -> None: """Disable notification for an event type(s) via the specified mechanism(s). Parameters ---------- event_type : constants.EventType Logical event identifier. mechanism : constants.EventMechanism Specifies event handling mechanisms to be disabled. """ self.visalib.disable_event(self.session, event_type, mechanism) def discard_events( self, event_type: constants.EventType, mechanism: constants.EventMechanism ) -> None: """Discards event occurrences for an event type and mechanism in this resource. Parameters ---------- event_type : constants.EventType Logical event identifier. mechanism : constants.EventMechanism Specifies event handling mechanisms to be disabled. """ self.visalib.discard_events(self.session, event_type, mechanism) def enable_event( self, event_type: constants.EventType, mechanism: constants.EventMechanism, context: None = None, ) -> None: """Enable event occurrences for specified event types and mechanisms in this resource. Parameters ---------- event_type : constants.EventType Logical event identifier. mechanism : constants.EventMechanism Specifies event handling mechanisms to be enabled context : None Not currently used, leave as None. """ self.visalib.enable_event(self.session, event_type, mechanism, context) def wait_on_event( self, in_event_type: constants.EventType, timeout: int, capture_timeout: bool = False, ) -> WaitResponse: """Waits for an occurrence of the specified event in this resource. in_event_type : constants.EventType Logical identifier of the event(s) to wait for. timeout : int Absolute time period in time units that the resource shall wait for a specified event to occur before returning the time elapsed error. The time unit is in milliseconds. None means waiting forever if necessary. capture_timeout : bool, optional When True will not produce a VisaIOError(VI_ERROR_TMO) but instead return a WaitResponse with timed_out=True. Returns ------- WaitResponse Object that contains event_type, context and ret value. """ try: event_type, context, ret = self.visalib.wait_on_event( self.session, in_event_type, timeout ) except errors.VisaIOError as exc: if capture_timeout and exc.error_code == constants.StatusCode.error_timeout: return WaitResponse( in_event_type, None, constants.StatusCode.error_timeout, self.visalib, timed_out=True, ) raise return WaitResponse(event_type, context, ret, self.visalib) def lock( self, timeout: Union[float, Literal["default"]] = "default", requested_key: Optional[str] = None, ) -> str: """Establish a shared lock to the resource. Parameters ---------- timeout : Union[float, Literal["default"]], optional Absolute time period (in milliseconds) that a resource waits to get unlocked by the locking session before returning an error. Defaults to "default" which means use self.timeout. requested_key : Optional[str], optional Access key used by another session with which you want your session to share a lock or None to generate a new shared access key. Returns ------- str A new shared access key if requested_key is None, otherwise, same value as the requested_key """ tout = cast(float, self.timeout if timeout == "default" else timeout) clean_timeout = util.cleanup_timeout(tout) return self.visalib.lock( self.session, constants.Lock.shared, clean_timeout, requested_key )[0] def lock_excl(self, timeout: Union[float, Literal["default"]] = "default") -> None: """Establish an exclusive lock to the resource. Parameters ---------- timeout : Union[float, Literal["default"]], optional Absolute time period (in milliseconds) that a resource waits to get unlocked by the locking session before returning an error. Defaults to "default" which means use self.timeout. """ tout = cast(float, self.timeout if timeout == "default" else timeout) clean_timeout = util.cleanup_timeout(tout) self.visalib.lock(self.session, constants.Lock.exclusive, clean_timeout, None) def unlock(self) -> None: """Relinquishes a lock for the specified resource.""" self.visalib.unlock(self.session) @contextlib.contextmanager def lock_context( self, timeout: Union[float, Literal["default"]] = "default", requested_key: Optional[str] = "exclusive", ) -> Iterator[Optional[str]]: """A context that locks Parameters ---------- timeout : Union[float, Literal["default"]], optional Absolute time period (in milliseconds) that a resource waits to get unlocked by the locking session before returning an error. Defaults to "default" which means use self.timeout. requested_key : Optional[str], optional When using default of 'exclusive' the lock is an exclusive lock. Otherwise it is the access key for the shared lock or None to generate a new shared access key. Yields ------ Optional[str] The access_key if applicable. """ if requested_key == "exclusive": self.lock_excl(timeout) access_key = None else: access_key = self.lock(timeout, requested_key) try: yield access_key finally: self.unlock() Resource.register(constants.InterfaceType.unknown, "")(Resource) pyvisa-1.11.3/pyvisa/resources/serial.py000066400000000000000000000054041375165327600203100ustar00rootroot00000000000000# -*- coding: utf-8 -*- """High level wrapper for Serial resources. This file is part of PyVISA. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ from .. import attributes, constants from ..attributes import Attribute from .messagebased import MessageBasedResource @MessageBasedResource.register(constants.InterfaceType.asrl, "INSTR") class SerialInstrument(MessageBasedResource): """Communicates with devices of type ASRL[::INSTR] Do not instantiate directly, use :meth:`pyvisa.highlevel.ResourceManager.open_resource`. """ #: Baud rate of the interface. baud_rate: Attribute[int] = attributes.AttrVI_ATTR_ASRL_BAUD() #: Number of data bits contained in each frame (from 5 to 8). data_bits: Attribute[int] = attributes.AttrVI_ATTR_ASRL_DATA_BITS() #: Parity used with every frame transmitted and received. parity: Attribute[constants.Parity] = attributes.AttrVI_ATTR_ASRL_PARITY() #: Number of stop bits used to indicate the end of a frame. stop_bits: Attribute[constants.StopBits] = attributes.AttrVI_ATTR_ASRL_STOP_BITS() #: Indicates the type of flow control used by the transfer mechanism. flow_control: Attribute[ constants.ControlFlow ] = attributes.AttrVI_ATTR_ASRL_FLOW_CNTRL() #: Number of bytes available in the low- level I/O receive buffer. bytes_in_buffer: Attribute[int] = attributes.AttrVI_ATTR_ASRL_AVAIL_NUM() #: If set to True, NUL characters are discarded. discard_null: Attribute[bool] = attributes.AttrVI_ATTR_ASRL_DISCARD_NULL() #: Manually control transmission. allow_transmit: Attribute[bool] = attributes.AttrVI_ATTR_ASRL_ALLOW_TRANSMIT() #: Method used to terminate read operations. end_input: Attribute[ constants.SerialTermination ] = attributes.AttrVI_ATTR_ASRL_END_IN() #: Method used to terminate write operations. end_output: Attribute[ constants.SerialTermination ] = attributes.AttrVI_ATTR_ASRL_END_OUT() #: Duration (in milliseconds) of the break signal. break_length: Attribute[int] = attributes.AttrVI_ATTR_ASRL_BREAK_LEN() #: Manually control the assertion state of the break signal. break_state: Attribute[ constants.LineState ] = attributes.AttrVI_ATTR_ASRL_BREAK_STATE() #: Character to be used to replace incoming characters that arrive with errors. replace_char: Attribute[str] = attributes.AttrVI_ATTR_ASRL_REPLACE_CHAR() #: XOFF character used for XON/XOFF flow control (both directions). xoff_char: Attribute[str] = attributes.AttrVI_ATTR_ASRL_XOFF_CHAR() #: XON character used for XON/XOFF flow control (both directions). xon_char: Attribute[str] = attributes.AttrVI_ATTR_ASRL_XON_CHAR() pyvisa-1.11.3/pyvisa/resources/tcpip.py000066400000000000000000000023021375165327600201420ustar00rootroot00000000000000# -*- coding: utf-8 -*- """High level wrapper for TCPIP resources. This file is part of PyVISA. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ from .. import constants from .messagebased import ControlRenMixin, MessageBasedResource from .resource import Resource @Resource.register(constants.InterfaceType.tcpip, "INSTR") class TCPIPInstrument(ControlRenMixin, MessageBasedResource): """Communicates with to devices of type TCPIP::host address[::INSTR] More complex resource names can be specified with the following grammar: TCPIP[board]::host address[::LAN device name][::INSTR] Do not instantiate directly, use :meth:`pyvisa.highlevel.ResourceManager.open_resource`. """ pass @Resource.register(constants.InterfaceType.tcpip, "SOCKET") class TCPIPSocket(MessageBasedResource): """Communicates with to devices of type TCPIP::host address::port::SOCKET More complex resource names can be specified with the following grammar: TCPIP[board]::host address::port::SOCKET Do not instantiate directly, use :meth:`pyvisa.highlevel.ResourceManager.open_resource`. """ pass pyvisa-1.11.3/pyvisa/resources/usb.py000066400000000000000000000116271375165327600176260ustar00rootroot00000000000000# -*- coding: utf-8 -*- """High level wrapper for USB resources. This file is part of PyVISA. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ from .. import attributes, constants from ..attributes import Attribute from .messagebased import ControlRenMixin, MessageBasedResource class USBCommon(MessageBasedResource): """Common class for USB resources.""" #: USB interface number used by the given session. interface_number: Attribute[int] = attributes.AttrVI_ATTR_USB_INTFC_NUM() #: USB serial number of this device. serial_number: Attribute[str] = attributes.AttrVI_ATTR_USB_SERIAL_NUM() #: USB protocol used by this USB interface. usb_protocol: Attribute[int] = attributes.AttrVI_ATTR_USB_PROTOCOL() #: Maximum size of data that will be stored by any given USB interrupt. maximum_interrupt_size: Attribute[int] = attributes.AttrVI_ATTR_USB_MAX_INTR_SIZE() #: Manufacturer name. manufacturer_name: Attribute[str] = attributes.AttrVI_ATTR_MANF_NAME() #: Manufacturer identification number of the device. manufacturer_id: Attribute[int] = attributes.AttrVI_ATTR_MANF_ID() #: Model name of the device. model_name: Attribute[str] = attributes.AttrVI_ATTR_MODEL_NAME() #: Model code for the device. model_code: Attribute[int] = attributes.AttrVI_ATTR_MODEL_CODE() @MessageBasedResource.register(constants.InterfaceType.usb, "INSTR") class USBInstrument(ControlRenMixin, USBCommon): """USB INSTR resources USB::manufacturer ID::model code::serial number More complex resource names can be specified with the following grammar: USB[board]::manufacturer ID::model code::serial number[::USB interface number][::INSTR] Do not instantiate directly, use :meth:`pyvisa.highlevel.ResourceManager.open_resource`. """ #: Whether the device is 488.2 compliant. is_4882_compliant: Attribute[bool] = attributes.AttrVI_ATTR_4882_COMPLIANT() def control_in( self, request_type_bitmap_field: int, request_id: int, request_value: int, index: int, length: int = 0, ) -> bytes: """Performs a USB control pipe transfer from the device. Parameters ---------- request_type_bitmap_field : int bmRequestType parameter of the setup stage of a USB control transfer. request_id : int bRequest parameter of the setup stage of a USB control transfer. request_value : int wValue parameter of the setup stage of a USB control transfer. index : int wIndex parameter of the setup stage of a USB control transfer. This is usually the index of the interface or endpoint. length : int wLength parameter of the setup stage of a USB control transfer. This value also specifies the size of the data buffer to receive the data from the optional data stage of the control transfer. Returns ------- bytes The data buffer that receives the data from the optional data stage of the control transfer. """ return self.visalib.usb_control_in( self.session, request_type_bitmap_field, request_id, request_value, index, length, )[0] def control_out( self, request_type_bitmap_field: int, request_id: int, request_value: int, index: int, data: bytes = b"", ): """Performs a USB control pipe transfer to the device. Parameters ---------- request_type_bitmap_field : int bmRequestType parameter of the setup stage of a USB control transfer. request_id : int bRequest parameter of the setup stage of a USB control transfer. request_value : int wValue parameter of the setup stage of a USB control transfer. index : int wIndex parameter of the setup stage of a USB control transfer. This is usually the index of the interface or endpoint. data : str The data buffer that sends the data in the optional data stage of the control transfer. """ return self.visalib.usb_control_out( self.session, request_type_bitmap_field, request_id, request_value, index, data, ) @MessageBasedResource.register(constants.InterfaceType.usb, "RAW") class USBRaw(USBCommon): """USB RAW resources: USB::manufacturer ID::model code::serial number::RAW More complex resource names can be specified with the following grammar: USB[board]::manufacturer ID::model code::serial number[::USB interface number]::RAW Do not instantiate directly, use :meth:`pyvisa.highlevel.ResourceManager.open_resource`. """ pyvisa-1.11.3/pyvisa/resources/vxi.py000066400000000000000000000056541375165327600176460ustar00rootroot00000000000000# -*- coding: utf-8 -*- """High level wrapper for VXI resources. This file is part of PyVISA. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ from .. import attributes, constants from ..attributes import Attribute from .registerbased import RegisterBasedResource from .resource import Resource @Resource.register(constants.InterfaceType.vxi, "BACKPLANE") class VXIBackplane(Resource): """Communicates with to devices of type VXI::BACKPLANE More complex resource names can be specified with the following grammar: VXI[board][::VXI logical address]::BACKPLANE Do not instantiate directly, use :meth:`pyvisa.highlevel.ResourceManager.open_resource`. """ class VXICommon(RegisterBasedResource): """Common parent class for VXI INSTR and MEMACC resources.""" #: Number of elements by which to increment the source offset after a transfer. source_increment: Attribute[int] = attributes.AttrVI_ATTR_SRC_INCREMENT() #: Number of elements by which to increment the destination offset after a transfer. destination_increment: Attribute[int] = attributes.AttrVI_ATTR_DEST_INCREMENT() #: Should I/O accesses use DMA (True) or Programmed I/O (False). allow_dma: Attribute[bool] = attributes.AttrVI_ATTR_DMA_ALLOW_EN() @Resource.register(constants.InterfaceType.vxi, "INSTR") class VXIInstrument(VXICommon): """Communicates with to devices of type VXI::VXI logical address[::INSTR] More complex resource names can be specified with the following grammar: VXI[board]::VXI logical address[::INSTR] Do not instantiate directly, use :meth:`pyvisa.highlevel.ResourceManager.open_resource`. """ #: Manufacturer name. manufacturer_name: Attribute[str] = attributes.AttrVI_ATTR_MANF_NAME() #: Manufacturer identification number of the device. manufacturer_id: Attribute[int] = attributes.AttrVI_ATTR_MANF_ID() #: Model name of the device. model_name: Attribute[str] = attributes.AttrVI_ATTR_MODEL_NAME() #: Model code for the device. model_code: Attribute[int] = attributes.AttrVI_ATTR_MODEL_CODE() #: Whether the device is 488.2 compliant. is_4882_compliant: Attribute[bool] = attributes.AttrVI_ATTR_4882_COMPLIANT() #: Should END be asserted during the transfer of the last byte of the buffer. send_end: Attribute[bool] = attributes.AttrVI_ATTR_SEND_END_EN() #: IO protocol to use. See the attribute definition for more details. io_protocol: Attribute[constants.IOProtocol] = attributes.AttrVI_ATTR_IO_PROT() @Resource.register(constants.InterfaceType.vxi, "MEMACC") class VXIMemory(VXICommon): """Communicates with to devices of type VXI[board]::MEMACC More complex resource names can be specified with the following grammar: VXI[board]::MEMACC Do not instantiate directly, use :meth:`pyvisa.highlevel.ResourceManager.open_resource`. """ pyvisa-1.11.3/pyvisa/rname.py000066400000000000000000000574001375165327600161240ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Functions and classes to parse and assemble resource name. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ import contextlib import re from collections import defaultdict from dataclasses import dataclass, field, fields from typing import ( TYPE_CHECKING, Callable, Dict, Iterable, List, Optional, Set, Tuple, Type, TypeVar, ) from typing_extensions import ClassVar from . import constants, errors, logger if TYPE_CHECKING: from .resources import Resource # noqa # pragma: no cover #: Interface types for which a subclass of ResourName exists _INTERFACE_TYPES: Set[str] = set() #: Resource Class for Interface type _RESOURCE_CLASSES: Dict[str, Set[str]] = defaultdict(set) #: Subclasses of ResourceName matching an interface type, resource class pair _SUBCLASSES: Dict[Tuple[str, str], Type["ResourceName"]] = {} # DEFAULT Resource Class for a given interface type. _DEFAULT_RC: Dict[str, str] = {} class InvalidResourceName(ValueError): """Exception raised when the resource name cannot be parsed.""" def __init__(self, msg: str) -> None: self.msg = msg @classmethod def bad_syntax( cls, syntax: str, resource_name: str, ex: Exception = None ) -> "InvalidResourceName": """Build an exception when the resource name cannot be parsed.""" if ex: msg = "The syntax is '%s' (%s)." % (syntax, ex) else: msg = "The syntax is '%s'." % syntax msg = "Could not parse '%s'. %s" % (resource_name, msg) return cls(msg) @classmethod def subclass_notfound( cls, interface_type_resource_class: Tuple[str, str], resource_name: str = None ) -> "InvalidResourceName": """Build an exception when no parser has been registered for a pair.""" msg = "Parser not found for: %s." % (interface_type_resource_class,) if resource_name: msg = "Could not parse '%s'. %s" % (resource_name, msg) return cls(msg) @classmethod def rc_notfound( cls, interface_type: str, resource_name: str = None ) -> "InvalidResourceName": """Build an exception when no resource class is provided and no default is found.""" msg = ( "Resource class for %s not provided and default not found." % interface_type ) if resource_name: msg = "Could not parse '%s'. %s" % (resource_name, msg) return cls(msg) def __str__(self) -> str: return self.msg T = TypeVar("T", bound=Type["ResourceName"]) def register_subclass(cls: T) -> T: """Register a subclass for a given interface type and resource class.""" # Assemble the format string based on the resource parts fmt = cls.interface_type syntax = cls.interface_type for ndx, f in enumerate(fields(cls)): sep = "::" if ndx else "" fmt += sep + "{0.%s}" % f.name if not f.default: syntax += sep + f.name.replace("_", " ") else: syntax += "[" + sep + f.name.replace("_", " ") + "]" fmt += "::" + cls.resource_class if not cls.is_rc_optional: syntax += "::" + cls.resource_class else: syntax += "[" + "::" + cls.resource_class + "]" cls._visa_syntax = syntax cls._canonical_fmt = fmt key = cls.interface_type, cls.resource_class if key in _SUBCLASSES: raise ValueError("Class already registered for %s and %s" % key) _SUBCLASSES[(cls.interface_type, cls.resource_class)] = cls _INTERFACE_TYPES.add(cls.interface_type) _RESOURCE_CLASSES[cls.interface_type].add(cls.resource_class) if cls.is_rc_optional: if cls.interface_type in _DEFAULT_RC: raise ValueError("Default already specified for %s" % cls.interface_type) _DEFAULT_RC[cls.interface_type] = cls.resource_class return cls class ResourceName: """Base class for ResourceNames to be used as a mixin.""" #: Interface type string interface_type: ClassVar[str] #: Resource class string resource_class: ClassVar[str] #: Specifices if the resource class part of the string is optional. is_rc_optional: ClassVar[bool] = False #: Formatting string for canonical _canonical_fmt: str = field(init=False) #: VISA syntax for resource _visa_syntax: str = field(init=False) #: VISA syntax for resource _fields: Tuple[str, ...] = field(init=False) #: Resource name provided by the user (not empty only when parsing) user: str = field(init=False) def __post_init__(self): # Ensure that all mandatory arguments have been passed for f in fields(self): if not getattr(self, f.name): raise TypeError(f.name + " is a required parameter") self._fields = tuple(f.name for f in fields(self)) @property def interface_type_const(self) -> constants.InterfaceType: try: return getattr(constants.InterfaceType, self.interface_type.lower()) except Exception: return constants.InterfaceType.unknown @classmethod def from_string(cls, resource_name: str) -> "ResourceName": """Parse a resource name and return a ResourceName Parameters ---------- resource_name : str Name of the resource Raises ------ InvalidResourceName Raised if the resource name is invalid. """ # TODO Remote VISA uname = resource_name.upper() for interface_type in _INTERFACE_TYPES: # Loop through all known interface types until we found one # that matches the beginning of the resource name if not uname.startswith(interface_type): continue parts: List[str] if len(resource_name) == len(interface_type): parts = [] else: parts = resource_name[len(interface_type) :].split("::") # Try to match the last part of the resource name to # one of the known resource classes for the given interface type. # If not possible, use the default resource class # for the given interface type. if parts and parts[-1] in _RESOURCE_CLASSES[interface_type]: parts, resource_class = parts[:-1], parts[-1] else: try: resource_class = _DEFAULT_RC[interface_type] except KeyError: raise InvalidResourceName.rc_notfound(interface_type, resource_name) # Look for the subclass try: subclass = _SUBCLASSES[(interface_type, resource_class)] except KeyError: raise InvalidResourceName.subclass_notfound( (interface_type, resource_class), resource_name ) # And create the object try: rn = subclass.from_parts(*parts) rn.user = resource_name return rn except (ValueError, TypeError) as ex: raise InvalidResourceName.bad_syntax( subclass._visa_syntax, resource_name, ex ) raise InvalidResourceName( "Could not parse %s: unknown interface type" % resource_name ) @classmethod def from_kwargs(cls, **kwargs) -> "ResourceName": """Build a resource from keyword arguments.""" interface_type = kwargs.pop("interface_type") if interface_type not in _INTERFACE_TYPES: raise InvalidResourceName("Unknown interface type: %s" % interface_type) try: resource_class = kwargs.pop("resource_class", _DEFAULT_RC[interface_type]) except KeyError: raise InvalidResourceName.rc_notfound(interface_type) # Look for the subclass try: subclass = _SUBCLASSES[(interface_type, resource_class)] except KeyError: raise InvalidResourceName.subclass_notfound( (interface_type, resource_class) ) # And create the object try: # Always use for subclasses that do take arguments return subclass(**kwargs) # type: ignore except (ValueError, TypeError) as ex: raise InvalidResourceName(str(ex)) # Implemented when building concrete subclass in build_rn_class @classmethod def from_parts(cls, *parts): """Construct a resource name from a list of parts.""" resource_parts = fields(cls) if len(parts) < sum(1 for f in resource_parts if f.default): raise ValueError("not enough parts") elif len(parts) > len(resource_parts): raise ValueError("too many parts") k, rp = resource_parts[0], resource_parts[1:] # The first part (just after the interface_type) is the only # optional part which can be empty and therefore the # default value should be used. p, pending = parts[0], parts[1:] kwargs = {k.name: k.default if p == "" else p} # The rest of the parts are consumed when mandatory elements are required. while len(pending) < len(rp): k, rp = rp[0], rp[1:] if not k.default: # This is impossible as far as I can tell for currently implemented # resource names if not pending: raise ValueError(k.name + " part is mandatory") # pragma: no cover p, pending = pending[0], pending[1:] if not p: raise ValueError(k.name + " part is mandatory") kwargs[k.name] = p else: kwargs[k.name] = k.default # When the length of the pending provided and resource parts # are equal, we just consume everything. kwargs.update((k.name, p) for k, p in zip(rp, pending)) return cls(**kwargs) def __str__(self): return self._canonical_fmt.format(self) # Build subclasses for each resource @register_subclass @dataclass class GPIBInstr(ResourceName): """GPIB INSTR The syntax is: GPIB[board]::primary_address[::secondary_address][::INSTR] """ #: GPIB board to use. board: str = "0" #: Primary address of the device to connect to primary_address: str = "" #: Secondary address of the device to connect to # Reference for the GPIB secondary address # https://www.mathworks.com/help/instrument/secondaryaddress.html secondary_address: str = "0" interface_type: ClassVar[str] = "GPIB" resource_class: ClassVar[str] = "INSTR" is_rc_optional: ClassVar[bool] = True @register_subclass @dataclass class GPIBIntfc(ResourceName): """GPIB INTFC The syntax is: GPIB[board]::INTFC """ #: GPIB board to use. board: str = "0" interface_type: ClassVar[str] = "GPIB" resource_class: ClassVar[str] = "INTFC" @register_subclass @dataclass class ASRLInstr(ResourceName): """ASRL INSTR The syntax is: ASRL[board]::INSTR """ #: Serial connection to use. board: str = "0" interface_type: ClassVar[str] = "ASRL" resource_class: ClassVar[str] = "INSTR" is_rc_optional: ClassVar[bool] = True @register_subclass @dataclass class TCPIPInstr(ResourceName): """TCPIP INSTR The syntax is: TCPIP[board]::host address[::LAN device name][::INSTR] """ #: Board to use. board: str = "0" #: Host address of the device (IPv4 or host name) host_address: str = "" #: LAN device name of the device lan_device_name: str = "inst0" interface_type: ClassVar[str] = "TCPIP" resource_class: ClassVar[str] = "INSTR" is_rc_optional: ClassVar[bool] = True @register_subclass @dataclass class TCPIPSocket(ResourceName): """TCPIP SOCKET The syntax is: TCPIP[board]::host address[::port]::SOCKET """ #: Board to use board: str = "0" #: Host address of the device (IPv4 or host name) host_address: str = "" #: Port on which to establish the connection port: str = "" interface_type: ClassVar[str] = "TCPIP" resource_class: ClassVar[str] = "SOCKET" @register_subclass @dataclass class USBInstr(ResourceName): """USB INSTR The syntax is: USB[board]::manufacturer ID::model code::serial number[::USB interface number][::INSTR] """ #: USB board to use. board: str = "0" #: ID of the instrument manufacturer. manufacturer_id: str = "" #: Code identifying the model of the instrument. model_code: str = "" #: Serial number of the instrument. serial_number: str = "" #: USB interface number. usb_interface_number: str = "0" interface_type: ClassVar[str] = "USB" resource_class: ClassVar[str] = "INSTR" is_rc_optional: ClassVar[bool] = True @register_subclass @dataclass class USBRaw(ResourceName): """USB RAW The syntax is: USB[board]::manufacturer ID::model code::serial number[::USB interface number]::RAW """ #: USB board to use. board: str = "0" #: ID of the instrument manufacturer. manufacturer_id: str = "" #: Code identifying the model of the instrument. model_code: str = "" #: Serial number of the instrument. serial_number: str = "" #: USB interface number. usb_interface_number: str = "0" interface_type: ClassVar[str] = "USB" resource_class: ClassVar[str] = "RAW" @register_subclass @dataclass class PXIBackplane(ResourceName): """PXI BACKPLANE The syntax is: PXI[interface]::chassis number::BACKPLANE """ #: PXI interface number. interface: str = "0" #: PXI chassis number chassis_number: str = "" interface_type: ClassVar[str] = "PXI" resource_class: ClassVar[str] = "BACKPLANE" @register_subclass @dataclass class PXIMemacc(ResourceName): """PXI MEMACC The syntax is: PXI[interface]::MEMACC """ #: PXI interface number interface: str = "0" interface_type: ClassVar[str] = "PXI" resource_class: ClassVar[str] = "MEMACC" @register_subclass @dataclass class VXIBackplane(ResourceName): """VXI BACKPLANE The syntax is: VXI[board]::VXI logical address::BACKPLANE """ #: VXI board board: str = "0" #: VXI logical address vxi_logical_address: str = "" interface_type: ClassVar[str] = "VXI" resource_class: ClassVar[str] = "BACKPLANE" @register_subclass @dataclass class VXIInstr(ResourceName): """VXI INSTR The syntax is: VXI[board]::VXI logical address[::INSTR] """ #: VXI board board: str = "0" #: VXI logical address vxi_logical_address: str = "" interface_type: ClassVar[str] = "VXI" resource_class: ClassVar[str] = "INSTR" is_rc_optional: ClassVar[bool] = True @register_subclass @dataclass class VXIMemacc(ResourceName): """VXI MEMACC The syntax is: VXI[board]::MEMACC """ #: VXI board board: str = "0" interface_type: ClassVar[str] = "VXI" resource_class: ClassVar[str] = "MEMACC" @register_subclass @dataclass class VXIServant(ResourceName): """VXI SERVANT The syntax is: VXI[board]::SERVANT """ #: VXI board board: str = "0" interface_type: ClassVar[str] = "VXI" resource_class: ClassVar[str] = "SERVANT" # TODO 3 types of PXI INSTR # TODO ENET-Serial INSTR # TODO Remote NI-VISA def assemble_canonical_name(**kwargs) -> str: """Build the canonical resource name from a set of keyword arguments.""" return str(ResourceName.from_kwargs(**kwargs)) def to_canonical_name(resource_name: str) -> str: """Parse a resource name and return the canonical version.""" return str(ResourceName.from_string(resource_name)) parse_resource_name = ResourceName.from_string def filter(resources: Iterable[str], query: str) -> Tuple[str, ...]: r"""Filter a list of resources according to a query expression. The search criteria specified in the query parameter has two parts: 1. a VISA regular expression over a resource string. 2. optional logical expression over attribute values (not implemented in this function, see below). .. note: The VISA regular expression syntax is not the same as the Python regular expression syntax. (see below) The regular expression is matched against the resource strings of resources known to the VISA Resource Manager. If the resource string matches the regular expression, the attribute values of the resource are then matched against the expression over attribute values. If the match is successful, the resource has met the search criteria and gets added to the list of resources found. By using the optional attribute expression, you can construct flexible and powerful expressions with the use of logical ANDs (&&), ORs(||), and NOTs (!). You can use equal (==) and unequal (!=) comparators to compare attributes of any type, and other inequality comparators (>, <, >=, <=) to compare attributes of numeric type. Use only global attributes in the attribute expression. Local attributes are not allowed in the logical expression part of the expr parameter. Symbol Meaning ---------- ---------- ? Matches any one character. \ Makes the character that follows it an ordinary character instead of special character. For example, when a question mark follows a backslash (\?), it matches the ? character instead of any one character. [list] Matches any one character from the enclosed list. You can use a hyphen to match a range of characters. [^list] Matches any character not in the enclosed list. You can use a hyphen to match a range of characters. * Matches 0 or more occurrences of the preceding character or expression. + Matches 1 or more occurrences of the preceding character or expression. Exp|exp Matches either the preceding or following expression. The or operator | matches the entire expression that precedes or follows it and not just the character that precedes or follows it. For example, VXI|GPIB means (VXI)|(GPIB), not VX(I|G)PIB. (exp) Grouping characters or expressions. """ if "{" in query: query, _ = query.split("{") logger.warning( "optional part of the query expression not supported. " "See filter2" ) try: query = query.replace("?", ".") matcher = re.compile(query, re.IGNORECASE) except re.error: raise errors.VisaIOError(constants.VI_ERROR_INV_EXPR) return tuple(res for res in resources if matcher.match(res)) class _AttrGetter: """Smart attr getter infering common attribute from resource name. Used to implement filter2 """ def __init__( self, resource_name: str, open_resource: Callable[[str], "Resource"] ) -> None: self.resource_name = resource_name self.parsed = parse_resource_name(resource_name) self.resource = None self.open_resource = open_resource def __getattr__(self, item): # noqa: C901 if item == "VI_ATTR_INTF_NUM": try: return int(self.parsed.board) except AttributeError: return int(self.interface) elif item == "VI_ATTR_MANF_ID": if not isinstance(self.parsed, (USBInstr, USBRaw)): raise self.raise_missing_attr(item) else: return self.parsed.manufacturer_id elif item == "VI_ATTR_MODEL_CODE": if not isinstance(self.parsed, (USBInstr, USBRaw)): raise self.raise_missing_attr(item) else: return self.parsed.model_code elif item == "VI_ATTR_USB_SERIAL_NUM": if not isinstance(self.parsed, (USBInstr, USBRaw)): raise self.raise_missing_attr(item) else: return self.parsed.serial_number elif item == "VI_ATTR_USB_INTFC_NUM": if not isinstance(self.parsed, (USBInstr, USBRaw)): raise self.raise_missing_attr(item) else: return int(self.parsed.board) elif item == "VI_ATTR_TCPIP_ADDR": if not isinstance(self.parsed, (TCPIPInstr, TCPIPSocket)): raise self.raise_missing_attr(item) else: return self.parsed.host_address elif item == "VI_ATTR_TCPIP_DEVICE_NAME": if not isinstance(self.parsed, TCPIPInstr): raise self.raise_missing_attr(item) else: return self.parsed.lan_device_name elif item == "VI_ATTR_TCPIP_PORT": if not isinstance(self.parsed, TCPIPSocket): raise self.raise_missing_attr(item) else: return int(self.parsed.port) elif item == "VI_ATTR_GPIB_PRIMARY_ADDR": if not isinstance(self.parsed, GPIBInstr): raise self.raise_missing_attr(item) else: return int(self.parsed.primary_address) elif item == "VI_ATTR_GPIB_SECONDARY_ADDR": if not isinstance(self.parsed, GPIBInstr): raise self.raise_missing_attr(item) else: return int(self.parsed.secondary_address) elif item == "VI_ATTR_PXI_CHASSIS": if not isinstance(self.parsed, PXIBackplane): raise self.raise_missing_attr(item) else: return int(self.parsed.chassis_number) elif item == "VI_ATTR_MAINFRAME_LA": if not isinstance(self.parsed, (VXIInstr, VXIBackplane)): raise self.raise_missing_attr(item) else: return int(self.parsed.vxi_logical_address) if self.resource is None: self.resource = self.open_resource(self.resource_name) return self.resource.get_visa_attribute(item) def raise_missing_attr(self, item): raise errors.VisaIOError(constants.VI_ERROR_NSUP_ATTR) def filter2( resources: Iterable[str], query: str, open_resource: Callable[[str], "Resource"] ) -> Tuple[str, ...]: """Filter a list of resources according to a query expression. It accepts the optional part of the expression. .. warning: This function is experimental and unsafe as it uses eval, It also might require to open the resource. Parameters ---------- resources : Iterable[str] Iterable of resource name to filter. query : str The pattern to use for filtering open_resource : Callable[[str], Resource] Function to open a resource (typically ResourceManager().open_resource) """ optional: Optional[str] if "{" in query: try: query, optional = query.split("{") optional, _ = optional.split("}") except ValueError: raise errors.VisaIOError(constants.VI_ERROR_INV_EXPR) else: optional = None filtered = filter(resources, query) if not optional: return tuple(filtered) optional = optional.replace("&&", "and").replace("||", "or").replace("!", "not ") optional = optional.replace("VI_", "res.VI_") @contextlib.contextmanager def open_close(resource_name): getter = _AttrGetter(resource_name, open_resource) yield getter if getter.resource is not None: getter.resource.close() selected = [] for rn in filtered: with open_close(rn) as getter: try: if eval(optional, None, dict(res=getter)): selected.append(rn) except Exception: logger.exception("Failed to evaluate %s on %s", optional, rn) return tuple(selected) pyvisa-1.11.3/pyvisa/shell.py000066400000000000000000000272361375165327600161350ustar00rootroot00000000000000#! /usr/bin/env python # -*- coding: utf-8 -*- """Shell for interactive testing. This file is taken from the Lantz Project. :copyright: (c) 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ import cmd from typing import List, Tuple from . import ResourceManager, VisaIOError, attributes, constants from .thirdparty import prettytable # TODO providing a way to list/use constants would be nice class VisaShell(cmd.Cmd): """Shell for interactive testing.""" intro: str = "\nWelcome to the VISA shell. Type help or ? to list commands.\n" prompt: str = "(visa) " use_rawinput: bool = True def __init__(self, library_path: str = ""): super().__init__() self.resource_manager = ResourceManager(library_path) self.default_prompt = self.prompt #: Resource list (used for autocomplete) #: Store a tuple with the name and the alias. self.resources: List[Tuple[str, str]] = [] #: Resource in use #: pyvisa.resources.Resource self.current = None self.py_attr: List[str] = [] self.vi_attr: List[str] = [] def do_list(self, args): """List all connected resources.""" try: resources = self.resource_manager.list_resources_info() except Exception as e: print(e) else: self.resources = [] for ndx, (resource_name, value) in enumerate(resources.items()): if not args: print("({0:2d}) {1}".format(ndx, resource_name)) if value.alias: print(" alias: {}".format(value.alias)) self.resources.append((resource_name, value.alias or None)) def do_open(self, args): """Open resource by number, resource name or alias: open 3""" if not args: print("A resource name must be specified.") return if self.current: print( "You can only open one resource at a time. Please close the current one first." ) return if args.isdigit(): try: args = self.resources[int(args)][0] except IndexError: print('Not a valid resource number. Use the command "list".') return try: self.current = self.resource_manager.open_resource(args) print( "{} has been opened.\n" 'You can talk to the device using "write", "read" or "query".\n' "The default end of message is added to each message.".format(args) ) self.py_attr = [] self.vi_attr = [] for attr in getattr(self.current, "visa_attributes_classes", ()): if attr.py_name: self.py_attr.append(attr.py_name) self.vi_attr.append(attr.visa_name) self.prompt = "(open) " except Exception as e: print(e) def complete_open(self, text, line, begidx, endidx): """Provide completion on open.""" if not self.resources: self.do_list("do not print") return [item[0] for item in self.resources if item[0].startswith(text)] + [ item[1] for item in self.resources if item[1] and item[1].startswith(text) ] def do_close(self, args): """Close resource in use.""" if not self.current: print('There are no resources in use. Use the command "open".') return try: self.current.close() except Exception as e: print(e) else: print("The resource has been closed.") self.current = None self.prompt = self.default_prompt def do_query(self, args): """Query resource in use: query *IDN? """ if not self.current: print('There are no resources in use. Use the command "open".') return try: print("Response: {}".format(self.current.query(args))) except Exception as e: print(e) def do_read(self, args): """Receive from the resource in use.""" if not self.current: print('There are no resources in use. Use the command "open".') return try: print(self.current.read()) except Exception as e: print(e) def do_write(self, args): """Send to the resource in use: send *IDN? """ if not self.current: print('There are no resources in use. Use the command "open".') return try: self.current.write(args) except Exception as e: print(e) def do_timeout(self, args): """Get or set timeout (in ms) for resource in use. Get timeout: timeout Set timeout: timeout """ if not self.current: print('There are no resources in use. Use the command "open".') return args = args.strip() if not args: try: print("Timeout: {}ms".format(self.current.timeout)) except Exception as e: print(e) else: args = args.split(" ") try: self.current.timeout = float(args[0]) print("Done") except Exception as e: print(e) def print_attribute_list(self): """Print the supported attribute list.""" p = prettytable.PrettyTable(("VISA name", "Constant", "Python name", "val")) for attr in getattr(self.current, "visa_attributes_classes", ()): try: val = self.current.get_visa_attribute(attr.attribute_id) except VisaIOError as e: val = e.abbreviation except Exception as e: val = str(e) if len(val) > 10: val = val[:10] + "..." p.add_row((attr.visa_name, attr.attribute_id, attr.py_name, val)) print(p.get_string(sortby="VISA name")) def do_attr(self, args): # noqa: C901 """Get or set the state for a visa attribute. List all attributes: attr Get an attribute state: attr Set an attribute state: attr """ if not self.current: print('There are no resources in use. Use the command "open".') return args = args.strip() if not args: self.print_attribute_list() return args = args.split(" ") if len(args) > 2: print( "Invalid syntax, use `attr ` to get; or `attr ` to set" ) return if len(args) == 1: # Get a given attribute attr_name = args[0] if attr_name.startswith("VI_"): try: print( self.current.get_visa_attribute(getattr(constants, attr_name)) ) except Exception as e: print(e) else: try: print(getattr(self.current, attr_name)) except Exception as e: print(e) return # Set the specified attribute value attr_name, attr_state = args[0], args[1] if attr_name.startswith("VI_"): try: attributeId = getattr(constants, attr_name) attr = attributes.AttributesByID[attributeId] datatype = attr.visa_type retcode = None if datatype == "ViBoolean": if attr_state == "True": attr_state = True elif attr_state == "False": attr_state = False else: retcode = ( constants.StatusCode.error_nonsupported_attribute_state ) elif datatype in [ "ViUInt8", "ViUInt16", "ViUInt32", "ViInt8", "ViInt16", "ViInt32", ]: try: attr_state = int(attr_state) except ValueError: retcode = ( constants.StatusCode.error_nonsupported_attribute_state ) if not retcode: retcode = self.current.set_visa_attribute(attributeId, attr_state) if retcode: print("Error {}".format(str(retcode))) else: print("Done") except Exception as e: print(e) else: print("Setting Resource Attributes by python name is not yet supported.") return def complete_attr(self, text, line, begidx, endidx): """Provide completion for the attr command.""" return [item for item in self.py_attr if item.startswith(text)] + [ item for item in self.vi_attr if item.startswith(text) ] def do_termchar(self, args): """Get or set termination character for resource in use. can be one of: CR, LF, CRLF, NUL or None. None is used to disable termination character Get termination character: termchar Set termination character read or read+write: termchar [] """ if not self.current: print('There are no resources in use. Use the command "open".') return args = args.strip() if not args: try: charmap = {u"\r": "CR", u"\n": "LF", u"\r\n": "CRLF", u"\0": "NUL"} chr = self.current.read_termination if chr in charmap: chr = charmap[chr] chw = self.current.write_termination if chw in charmap: chw = charmap[chw] print("Termchar read: {} write: {}".format(chr, chw)) except Exception as e: print(e) args = args.split(" ") if len(args) > 2: print( "Invalid syntax, use `termchar ` to set both " "read_termination and write_termination to the same value, or " "`termchar ` to use distinct values." ) else: charmap = { "CR": u"\r", "LF": u"\n", "CRLF": u"\r\n", "NUL": u"\0", "None": None, } chr = args[0] chw = args[0 if len(args) == 1 else 1] if chr in charmap and chw in charmap: try: self.current.read_termination = charmap[chr] self.current.write_termination = charmap[chw] print("Done") except Exception as e: print(e) else: print("use CR, LF, CRLF, NUL or None to set termchar") return def do_exit(self, arg): """Exit the shell session.""" if self.current: self.current.close() self.resource_manager.close() del self.resource_manager return True def do_EOF(self, arg): """Handle an EOF.""" return True def main(library_path=""): """Main entry point to start the shell.""" VisaShell(library_path).cmdloop() pyvisa-1.11.3/pyvisa/testsuite/000077500000000000000000000000001375165327600164735ustar00rootroot00000000000000pyvisa-1.11.3/pyvisa/testsuite/__init__.py000066400000000000000000000031261375165327600206060ustar00rootroot00000000000000# -*- coding: utf-8 -*- """PyVISA testsuite. """ import logging from logging.handlers import BufferingHandler import pytest from pyvisa import ResourceManager, logger try: ResourceManager() except ValueError: VISA_PRESENT = False else: VISA_PRESENT = True require_visa_lib = pytest.mark.skipif( not VISA_PRESENT, reason="Requires an installed VISA library. Run on PyVISA buildbot.", ) class TestHandler(BufferingHandler): def __init__(self, only_warnings=False): # BufferingHandler takes a "capacity" argument # so as to know when to flush. As we're overriding # shouldFlush anyway, we can set a capacity of zero. # You can call flush() manually to clear out the # buffer. self.only_warnings = only_warnings BufferingHandler.__init__(self, 0) def shouldFlush(self, record): return False def emit(self, record): if self.only_warnings and record.level != logging.WARNING: return self.buffer.append(record.__dict__) class BaseTestCase: CHECK_NO_WARNING = True def setup_method(self): self._test_handler = None if self.CHECK_NO_WARNING: self._test_handler = th = TestHandler() th.setLevel(logging.WARNING) logger.addHandler(th) def teardown_method(self): if self._test_handler is not None: buf = self._test_handler.buffer length = len(buf) msg = "\n".join(record.get("msg", str(record)) for record in buf) assert length == 0, "%d warnings raised.\n%s" % (length, msg) pyvisa-1.11.3/pyvisa/testsuite/fake-extensions/000077500000000000000000000000001375165327600215765ustar00rootroot00000000000000pyvisa-1.11.3/pyvisa/testsuite/fake-extensions/pyvisa_test.py000066400000000000000000000002351375165327600245220ustar00rootroot00000000000000# -*- coding: utf-8 -*- """ """ from pyvisa.highlevel import VisaLibraryBase class FalseVISALib(VisaLibraryBase): pass WRAPPER_CLASS = FalseVISALib pyvisa-1.11.3/pyvisa/testsuite/keysight_assisted_tests/000077500000000000000000000000001375165327600234435ustar00rootroot00000000000000pyvisa-1.11.3/pyvisa/testsuite/keysight_assisted_tests/__init__.py000066400000000000000000000026771375165327600255700ustar00rootroot00000000000000# -*- coding: utf-8 -*- """This package is meant to run against a PyVISA builbot. The PyVISA builbot is connected to a fake instrument implemented using the Keysight Virtual Instrument IO Test software. For this part of the testsuite to be run, you need to set the PYVISA_KEYSIGHT_VIRTUAL_INSTR environment value. To enable coverage for the shell, one needs to add/edit sitecustomize.py in site-packages and add the following:: import coverage coverage.process_startup() See https://coverage.readthedocs.io/en/v4.5.x/subprocess.html for details. """ import functools import os import types import pytest require_virtual_instr = pytest.mark.skipif( "PYVISA_KEYSIGHT_VIRTUAL_INSTR" not in os.environ, reason="Requires the Keysight virtual instrument. Run on PyVISA " "buildbot.", ) RESOURCE_ADDRESSES = { # "GPIB::INSTR": "GPIB::19::INSTR", # "USB::INSTR": "USB::", "TCPIP::INSTR": "TCPIP::127.0.0.1::INSTR", # ie localhost "TCPIP::SOCKET": "TCPIP::127.0.0.1::5025::SOCKET", } ALIASES = { "TCPIP::127.0.0.1::INSTR": "tcpip", } # Even a deepcopy is not a true copy of a function. def copy_func(f): """Based on http://stackoverflow.com/a/6528148/190597 (Glenn Maynard)""" g = types.FunctionType( f.__code__, f.__globals__, name=f.__name__, argdefs=f.__defaults__, closure=f.__closure__, ) g = functools.update_wrapper(g, f) g.__kwdefaults__ = f.__kwdefaults__ return g pyvisa-1.11.3/pyvisa/testsuite/keysight_assisted_tests/messagebased_resource_utils.py000066400000000000000000001017721375165327600315770ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Common test case for all message based resources. """ import ctypes import gc import logging import time import pytest from pyvisa import constants, errors from pyvisa.constants import EventType, ResourceAttribute from pyvisa.resources import Resource from .resource_utils import ( EventAwareResourceTestCaseMixin, LockableResourceTestCaseMixin, ResourceTestCase, ) try: import numpy as np # type: ignore except ImportError: np = None class EventHandler: """Event handler.""" def __init__(self) -> None: self.event_success = False self.srq_success = False self.io_completed = False self.handle = None self.session = None def handle_event(self, session, event_type, event, handle=None): """Event handler Ctypes handler are expected to return an interger. """ self.session = session self.handle = handle if event_type == EventType.service_request: self.event_success = True self.srq_success = True return 0 if event_type == EventType.io_completion: self.event_success = True self.io_completed = True return 0 else: self.event_success = True return 0 def simplified_handler(self, resource, event, handle=None): """Simplified handler that can be wrapped.""" self.session = resource.session self.handle = handle event_type = event.event_type if event_type == EventType.service_request: self.event_success = True self.srq_success = True return None elif event_type == EventType.io_completion: self.event_success = True self.io_completed = True return None else: self.event_success = True return None class MessagebasedResourceTestCase(ResourceTestCase): """Base test case for all message based resources.""" #: Type of resource being tested in this test case. #: See RESOURCE_ADDRESSES in the __init__.py file of this package for #: acceptable values RESOURCE_TYPE = "" # Any test involving communication involve to first write to glider the # data then request it to send it back def setup_method(self): """Create a resource using the address matching the type.""" super().setup_method() self.instr.write_termination = "\n" self.instr.read_termination = "\n" self.instr.timeout = 100 def compare_user_handle(self, h1, h2): """Function comparing to user handle as passed to a callback. We need such an indirection because we cannot safely always return a Python object and most ctypes object do not compare equal. """ if isinstance(h1, ctypes.Structure): return h1 == h2 elif hasattr(h1, "value"): return h1.value == h2.value else: # assume an array return all((i == j for i, j in zip(h1, h2))) def test_encoding(self): """Tets setting the string encoding.""" assert self.instr.encoding == "ascii" self.instr.encoding = "utf-8" with pytest.raises(LookupError): self.instr.encoding = "test" def test_termchars(self): """Test modifying the termchars.""" # Write termination self.instr.write_termination = "\r\n" assert self.instr.write_termination == "\r\n" self.instr.read_termination = "\r\0" assert self.instr.read_termination == "\r\0" assert self.instr.get_visa_attribute(ResourceAttribute.termchar) == ord("\0") assert self.instr.get_visa_attribute(ResourceAttribute.termchar_enabled) # Disable read termination self.instr.read_termination = None assert self.instr.get_visa_attribute(ResourceAttribute.termchar) == ord("\n") assert not self.instr.get_visa_attribute(ResourceAttribute.termchar_enabled) # Ban repeated term chars with pytest.raises(ValueError): self.instr.read_termination = "\n\n" def test_write_raw_read_bytes(self): """Test writing raw data and reading a specific number of bytes.""" # Reading all bytes at once self.instr.write_raw(b"RECEIVE\n") self.instr.write_raw(b"test\n") count = self.instr.write_raw(b"SEND\n") assert count == 5 self.instr.flush(constants.VI_READ_BUF) msg = self.instr.read_bytes(5, chunk_size=2) assert msg == b"test\n" # Reading one byte at a time self.instr.write_raw(b"RECEIVE\n") self.instr.write_raw(b"test\n") self.instr.write_raw(b"SEND\n") for ch in b"test\n": assert self.instr.read_bytes(1) == ch.to_bytes(1, "little") # Breaking on termchar self.instr.read_termination = "\r" self.instr.write_raw(b"RECEIVE\n") self.instr.write_raw(b"te\rst\r\n") self.instr.write_raw(b"SEND\n") assert self.instr.read_bytes(100, break_on_termchar=True) == b"te\r" assert self.instr.read_bytes(100, break_on_termchar=True) == b"st\r" assert self.instr.read_bytes(1) == b"\n" # Breaking on end of message self.instr.read_termination = "\n" self.instr.write_raw(b"RECEIVE\n") self.instr.write_raw(b"test\n") self.instr.write_raw(b"SEND\n") assert self.instr.read_bytes(100, break_on_termchar=True) == b"test\n" def test_handling_exception_in_read_bytes(self, caplog): """Test handling exception in read_bytes (monkeypatching)""" def false_read(session, size): raise errors.VisaIOError(constants.VI_ERROR_ABORT) read = self.instr.visalib.read self.instr.visalib.read = false_read with caplog.at_level(logging.DEBUG): try: self.instr.read_bytes(1) except errors.VisaIOError: pass finally: self.instr.visalib.read = read assert "- exception while reading:" in caplog.records[1].message def test_write_raw_read_raw(self): """Test writing raw data and reading an answer.""" self.instr.write_raw(b"RECEIVE\n") self.instr.write_raw(b"test\n") self.instr.write_raw(b"SEND\n") assert self.instr.read_raw(size=2) == b"test\n" def test_clear(self): """Test clearing the incoming buffer.""" self.instr.write_raw(b"RECEIVE\n") self.instr.write_raw(b"test\n") self.instr.write_raw(b"SEND\n") self.instr.clear() self.instr.timeout = 10 with pytest.raises(errors.VisaIOError): self.instr.read_raw() def test_write_read(self): """Test writing and reading.""" self.instr.write_termination = "\n" self.instr.read_termination = "\r\n" self.instr.write("RECEIVE") with pytest.warns(UserWarning): self.instr.write("test\r\n") count = self.instr.write("SEND") assert count == 5 assert self.instr.read() == "test" # Missing termination chars self.instr.read_termination = "\r\n" self.instr.write("RECEIVE") self.instr.write("test") self.instr.write("SEND") with pytest.warns(Warning): assert self.instr.read() == "test\n" # Dynamic termination self.instr.write_termination = "\r" self.instr.write("RECEIVE\n", termination=False) self.instr.write("test\r", termination="\n") self.instr.write("SEND", termination="\n") assert self.instr.read(termination="\r") == "test" # Test query self.instr.write_termination = "\n" self.instr.write("RECEIVE") self.instr.write("test\r") tic = time.time() assert self.instr.query("SEND", delay=0.5) == "test" assert time.time() - tic > 0.49 # Test handling repeated term char self.instr.read_termination = "\n" for char in ("\r", None): self.instr.write_termination = "\n" if char else "\r" self.instr.write("RECEIVE", termination="\n") with pytest.warns(Warning): self.instr.write("test\r", termination=char) self.instr.write("", termination="\n") self.instr.write("SEND", termination="\n") assert self.instr.read() == "test\r\r" # TODO not sure how to test encoding def test_handling_exception_in_read_raw(self, caplog): """Test handling exception in read_bytes (monkeypatching)""" def false_read(session, size): raise errors.VisaIOError(constants.VI_ERROR_ABORT) read = self.instr.visalib.read self.instr.visalib.read = false_read with caplog.at_level(logging.DEBUG): try: self.instr.read() except errors.VisaIOError: pass finally: self.instr.visalib.read = read assert caplog.records def test_write_ascii_values(self): """Test writing ascii values.""" # Standard separator values = [1, 2, 3, 4, 5] self.instr.write("RECEIVE") count = self.instr.write_ascii_values("", values, "d") assert count == 10 self.instr.write("SEND") assert self.instr.read() == "1,2,3,4,5" # Non standard separator and termination self.instr.write_termination = "\r" self.instr.write("RECEIVE", termination="\n") self.instr.write_ascii_values("", values, "d", separator=";", termination=False) self.instr.write("", termination="\n") self.instr.write("SEND", termination="\n") assert self.instr.read() == "1;2;3;4;5" # Test handling repeated term char for char in ("\r", None): self.instr.write_termination = "\n" if char else "\r" self.instr.write("RECEIVE", termination="\n") with pytest.warns(Warning): values = [1, 2, 3, 4, 5] self.instr.write_ascii_values( "\r", values, "s", separator=";", termination=char ) self.instr.write("", termination="\n") self.instr.write("SEND", termination="\n") assert self.instr.read() == "\r1;2;3;4;5\r" @pytest.mark.parametrize( "hfmt, prefix", zip(("ieee", "hp", "empty"), (b"#212", b"#A\x0c\x00", b"")) ) def test_write_binary_values(self, hfmt, prefix): """Test writing binary data.""" values = [1, 2, 3, 4, 5, 6] self.instr.write_termination = "\n" self.instr.write("RECEIVE") count = self.instr.write_binary_values("", values, "h", header_fmt=hfmt) # Each interger encoded as h uses 2 bytes assert count == len(prefix) + 12 + 1 self.instr.write("SEND") msg = self.instr.read_bytes(13 + len(prefix)) assert msg == prefix + b"\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\n" if hfmt == "hp": fl_prefix = prefix[0:2] + prefix[-2::][::-1] else: fl_prefix = prefix self.instr.write_termination = "\r" self.instr.write("RECEIVE", termination="\n") self.instr.write_binary_values( "", values, "h", is_big_endian=True, termination=False, header_fmt=hfmt ) self.instr.write("", termination="\n") self.instr.write("SEND", termination="\n") assert ( self.instr.read_bytes(13 + len(prefix)) == fl_prefix + b"\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\n" ) # Test handling repeated term char for char in ("\r", None): self.instr.write_termination = "\n" if char else "\r" self.instr.write("RECEIVE", termination="\n") with pytest.warns(Warning): self.instr.write_binary_values( "\r", values, "h", header_fmt=hfmt, termination=char ) self.instr.write("", termination="\n") self.instr.write("SEND", termination="\n") msg = self.instr.read() assert ( msg == "\r" + prefix.decode("ascii") + "\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\r" ) # Wrong header format with pytest.raises(ValueError): self.instr.write_binary_values("", values, "h", header_fmt="zxz") def test_read_ascii_values(self): """Test reading ascii values.""" # Standard separator self.instr.write("RECEIVE") self.instr.write("1,2,3,4,5") self.instr.write("SEND") values = self.instr.read_ascii_values() assert type(values[0]) is float assert values == [1.0, 2.0, 3.0, 4.0, 5.0] # Non standard separator and termination self.instr.write("RECEIVE") self.instr.write("1;2;3;4;5") tic = time.time() values = self.instr.query_ascii_values( "SEND", converter="d", separator=";", delay=0.5 ) assert time.time() - tic > 0.5 assert type(values[0]) is int assert values == [1, 2, 3, 4, 5] # Numpy container if np: self.instr.write("RECEIVE") self.instr.write("1,2,3,4,5") self.instr.write("SEND") values = self.instr.read_ascii_values(container=np.array) expected = np.array([1.0, 2.0, 3.0, 4.0, 5.0]) assert values.dtype is expected.dtype np.testing.assert_array_equal(values, expected) @pytest.mark.parametrize("hfmt", ("ieee", "hp")) def test_read_binary_values(self, hfmt): """Test reading binary data.""" # TODO test handling binary decoding issue (troublesome) self.instr.read_termination = "\r" # 3328 in binary short is \x00\r this way we can interrupt the # transmission midway to test some corner cases data = [1, 2, 3328, 3, 4, 5, 6, 7] self.instr.write("RECEIVE") self.instr.write_binary_values( "", data, "h", header_fmt=hfmt, termination="\r\n" ) self.instr.write("SEND") new = self.instr.read_binary_values( datatype="h", is_big_endian=False, header_fmt=hfmt, expect_termination=True, chunk_size=8, ) self.instr.read_bytes(1) assert data == new self.instr.write("RECEIVE") self.instr.write_binary_values( "", data, "h", header_fmt=hfmt, is_big_endian=True ) new = self.instr.query_binary_values( "SEND", datatype="h", header_fmt=hfmt, is_big_endian=True, expect_termination=False, chunk_size=8, container=np.array if np else list, ) self.instr.read_bytes(1) if np: np.testing.assert_array_equal(new, np.array(data, dtype=np.int16)) else: assert data == new def test_read_query_binary_values_invalid_header(self): """Test we properly handle an invalid header.""" data = [1, 2, 3328, 3, 4, 5, 6, 7] self.instr.write("RECEIVE") self.instr.write_binary_values( "", data, "h", header_fmt="ieee", is_big_endian=True ) self.instr.write("SEND") with pytest.raises(ValueError): self.instr.read_binary_values( datatype="h", is_big_endian=False, header_fmt="invalid", expect_termination=True, chunk_size=8, ) self.instr.write("RECEIVE") self.instr.write_binary_values( "", data, "h", header_fmt="ieee", is_big_endian=True ) with pytest.raises(ValueError): self.instr.query_binary_values( "*IDN", datatype="h", is_big_endian=False, header_fmt="invalid", expect_termination=True, chunk_size=8, ) # Not sure how to test this @pytest.mark.skip def test_handling_malformed_binary(self): """""" pass @pytest.mark.parametrize( "hfmt, header", zip(("ieee", "hp", "empty"), ("#10", "#A\x00\x00", "")) ) def test_read_binary_values_unreported_length(self, hfmt, header): """Test reading binary data.""" self.instr.read_termination = "\r" # 3328 in binary short is \x00\r this way we can interrupt the # transmission midway to test some corner cases data = [1, 2, 3328, 3, 4, 5] self.instr.write("RECEIVE") self.instr.write( header + "\x01\x00\x02\x00\x00\r\x03\x00\x04\x00\x05\x00", termination="\r\n", ) self.instr.write("SEND") new = self.instr.read_binary_values( datatype="h", is_big_endian=False, header_fmt=hfmt, expect_termination=True, chunk_size=6, data_points=6, ) self.instr.read_bytes(1) assert data == new self.instr.write("RECEIVE") self.instr.write( header + "\x00\x01\x00\x02\r\x00\x00\x03\x00\x04\x00\x05", termination="\r\n", ) new = self.instr.query_binary_values( "SEND", datatype="h", header_fmt=hfmt, is_big_endian=True, expect_termination=False, chunk_size=6, container=np.array if np else list, data_points=6, ) self.instr.read_bytes(1) if np: np.testing.assert_array_equal(new, np.array(data, dtype=np.int16)) else: assert data == new # Check we do error on unreported/unspecified length self.instr.write("RECEIVE") self.instr.write( header + "\x01\x00\x02\x00\x00\r\x03\x00\x04\x00\x05\x00", termination="\r\n", ) self.instr.write("SEND") with pytest.raises(ValueError): self.instr.read_binary_values( datatype="h", is_big_endian=False, header_fmt=hfmt, expect_termination=True, chunk_size=6, ) def test_delay_in_query_ascii(self): """Test handling of the delay argument in query_ascii_values.""" # Test using the instrument wide delay self.instr.query_delay = 1.0 self.instr.write("RECEIVE") self.instr.write("1,2,3,4,5") tic = time.perf_counter() values = self.instr.query_ascii_values("SEND") assert time.perf_counter() - tic > 0.99 assert type(values[0]) is float assert values == [1.0, 2.0, 3.0, 4.0, 5.0] # Test specifying the delay self.instr.query_delay = 0.0 self.instr.write("RECEIVE") self.instr.write("1,2,3,4,5") tic = time.perf_counter() values = self.instr.query_ascii_values("SEND", delay=1.0) assert time.perf_counter() - tic > 0.99 assert type(values[0]) is float assert values == [1.0, 2.0, 3.0, 4.0, 5.0] # Test specifying a 0 delay self.instr.query_delay = 1.0 self.instr.write("RECEIVE") self.instr.write("1,2,3,4,5") tic = time.perf_counter() values = self.instr.query_ascii_values("SEND", delay=0.0) assert time.perf_counter() - tic < 0.99 assert type(values[0]) is float assert values == [1.0, 2.0, 3.0, 4.0, 5.0] def test_instrument_wide_delay_in_query_binary(self): """Test handling delay in query_ascii_values.""" header = "#10" data = [1, 2, 3328, 3, 4, 5] # Test using the instrument wide delay self.instr.query_delay = 1.0 self.instr.write("RECEIVE") self.instr.write( header + "\x00\x01\x00\x02\r\x00\x00\x03\x00\x04\x00\x05", termination="\r\n", ) tic = time.perf_counter() new = self.instr.query_binary_values( "SEND", datatype="h", header_fmt="ieee", is_big_endian=True, expect_termination=False, chunk_size=6, data_points=6, ) assert time.perf_counter() - tic > 0.99 assert data == new def test_delay_args_in_query_binary(self): """Test handling of the delay argument in query_ascii_values.""" header = "#10" data = [1, 2, 3328, 3, 4, 5] self.instr.query_delay = 0.0 self.instr.write("RECEIVE") self.instr.write( header + "\x00\x01\x00\x02\r\x00\x00\x03\x00\x04\x00\x05", termination="\r\n", ) tic = time.perf_counter() new = self.instr.query_binary_values( "SEND", datatype="h", header_fmt="ieee", is_big_endian=True, expect_termination=False, chunk_size=6, data_points=6, delay=1.0, ) assert time.perf_counter() - tic > 0.99 assert data == new def test_no_delay_args_in_query_binary(self): """Test handling of the delay argument in query_ascii_values.""" header = "#10" data = [1, 2, 3328, 3, 4, 5] self.instr.query_delay = 1.0 self.instr.write("RECEIVE") self.instr.write( header + "\x00\x01\x00\x02\r\x00\x00\x03\x00\x04\x00\x05", termination="\r\n", ) tic = time.perf_counter() new = self.instr.query_binary_values( "SEND", datatype="h", header_fmt="ieee", is_big_endian=True, expect_termination=False, chunk_size=6, data_points=6, delay=0.0, ) assert time.perf_counter() - tic < 1.0 assert data == new def test_stb(self): """Test reading the status byte.""" assert 0 <= self.instr.stb <= 256 assert 0 <= self.instr.read_stb() <= 256 class EventAwareMessagebasedResourceTestCaseMixin(EventAwareResourceTestCaseMixin): """Mixin for message based resources supporting events.""" def test_manually_called_handlers(self): """Test calling manually even handler.""" class FalseResource(Resource): session = None visalib = None _session = None def __init__(self): pass fres = FalseResource() fres2 = FalseResource() fres2.session = 1 handler = EventHandler() false_wrapped_handler = fres.wrap_handler(handler.simplified_handler) false_wrapped_handler(None, EventType.clear, 1, 1) assert handler.event_success with pytest.raises(RuntimeError): false_wrapped_handler(1, EventType.clear, 1, 1) def test_handling_invalid_handler(self): """Test handling an error related to a wrong handler type.""" with pytest.raises(errors.VisaTypeError): event_type = EventType.exception self.instr.install_handler(event_type, 1, object()) def test_uninstalling_missing_visa_handler(self): """Test uninstalling a visa handler that was not registered.""" handler1 = EventHandler() handler2 = EventHandler() event_type = EventType.exception self.instr.install_handler(event_type, handler1.handle_event) with pytest.raises(errors.UnknownHandler): self.instr.uninstall_handler(event_type, handler2.handle_event) self.instr.uninstall_handler(event_type, handler1.handle_event) with pytest.raises(errors.UnknownHandler): self.instr.uninstall_handler(event_type, handler2.handle_event) def test_handler_clean_up_on_resource_del(self): """Test that handlers are properly cleaned when a resource is deleted.""" handler = EventHandler() event_type = EventType.exception self.instr.install_handler(event_type, handler.handle_event) self.instr = None gc.collect() assert not self.rm.visalib.handlers def test_uninstall_all_handlers(self): """Test uninstall all handlers from all sessions.""" handler = EventHandler() event_type = EventType.exception self.instr.install_handler(event_type, handler.handle_event) self.rm.visalib.uninstall_all_visa_handlers(None) assert not self.rm.visalib.handlers def test_manual_async_read(self): """Test handling IOCompletion event which has extra attributes.""" # Prepare message self.instr.write_raw(b"RECEIVE\n") self.instr.write_raw(b"test\n") self.instr.write_raw(b"SEND\n") # Enable event handling event_type = EventType.io_completion event_mech = constants.EventMechanism.queue wait_time = 2000 # set time that program waits to receive event self.instr.enable_event(event_type, event_mech, None) try: visalib = self.instr.visalib buffer, job_id, status_code = visalib.read_asynchronously( self.instr.session, 10 ) assert buffer is visalib.get_buffer_from_id(job_id) response = self.instr.wait_on_event(event_type, wait_time) finally: self.instr.disable_event(event_type, event_mech) assert response.event.status == constants.StatusCode.success assert bytes(buffer) == bytes(response.event.buffer) assert bytes(response.event.data) == b"test\n" assert response.event.return_count == 5 assert response.event.operation_name == "viReadAsync" def test_getting_unknown_buffer(self): """Test getting a buffer with a wrong ID.""" assert self.instr.visalib.get_buffer_from_id(1) is None def test_wait_on_event_timeout(self): """Test waiting on a VISA event.""" event_type = EventType.service_request event_mech = constants.EventMechanism.queue # Emit a clear to avoid dealing with previous requests self.instr.clear() self.instr.enable_event(event_type, event_mech, None) try: response = self.instr.wait_on_event(event_type, 10, capture_timeout=True) finally: self.instr.disable_event(event_type, event_mech) assert response.timed_out assert response.event.event_type == event_type with pytest.raises(errors.VisaIOError): self.instr.enable_event(event_type, event_mech, None) try: response = self.instr.wait_on_event(event_type, 10) finally: self.instr.disable_event(event_type, event_mech) def test_wait_on_event(self): """Test waiting on a VISA event.""" event_type = EventType.service_request event_mech = constants.EventMechanism.queue wait_time = 2000 # set time that program waits to receive event self.instr.enable_event(event_type, event_mech, None) self.instr.write("RCVSLOWSRQ") self.instr.write("1") self.instr.write("SENDSLOWSRQ") try: response = self.instr.wait_on_event(event_type, wait_time) finally: self.instr.disable_event(event_type, event_mech) assert not response.timed_out assert response.event.event_type == EventType.service_request assert self.instr.read() == "1" with pytest.warns(FutureWarning): response.event_type with pytest.warns(FutureWarning): response.context def test_managing_visa_handler(self): """Test using visa handlers.""" def _test(handle): handler = EventHandler() event_type = EventType.service_request event_mech = constants.EventMechanism.handler user_handle = self.instr.install_handler( event_type, handler.handle_event, user_handle=handle ) self.instr.enable_event(event_type, event_mech, None) self.instr.write("RCVSLOWSRQ") self.instr.write("1") self.instr.write("SENDSLOWSRQ") try: t1 = time.time() while not handler.event_success: if (time.time() - t1) > 2: break time.sleep(0.1) finally: self.instr.disable_event(event_type, event_mech) self.instr.uninstall_handler( event_type, handler.handle_event, user_handle ) assert handler.session == self.instr.session assert self.compare_user_handle(handler.handle, user_handle) assert handler.srq_success assert self.instr.read() == "1" self.instr.clear() class Point(ctypes.Structure): _fields_ = [("x", ctypes.c_int), ("y", ctypes.c_int)] def __eq__(self, other): if type(self) is not type(other): return False return self.x == other.x and self.y == other.y for handle in (1, 1.0, "1", [1], [1.0], Point(1, 2)): print(handle) _test(handle) def test_wrapping_handler(self): """Test wrapping a handler using a Resource.""" handler = EventHandler() event_type = EventType.service_request event_mech = constants.EventMechanism.handler wrapped_handler = self.instr.wrap_handler(handler.simplified_handler) user_handle = self.instr.install_handler(event_type, wrapped_handler, 1) self.instr.enable_event(event_type, event_mech, None) self.instr.write("RCVSLOWSRQ") self.instr.write("1") self.instr.write("SENDSLOWSRQ") try: t1 = time.time() while not handler.event_success: if (time.time() - t1) > 2: break time.sleep(0.1) finally: self.instr.disable_event(event_type, event_mech) self.instr.uninstall_handler(event_type, wrapped_handler, user_handle) assert self.instr.session == handler.session assert self.compare_user_handle(handler.handle, user_handle) assert handler.srq_success assert self.instr.read() == "1" def test_bare_handler(self): """Test using a bare handler passing raw backend values.""" from pyvisa import ctwrapper if not isinstance(self.instr.visalib, ctwrapper.IVIVisaLibrary): return ctwrapper.WRAP_HANDLER = False try: handler = EventHandler() event_type = EventType.service_request event_mech = constants.EventMechanism.handler user_handle = self.instr.install_handler( event_type, handler.handle_event, 1 ) self.instr.enable_event(event_type, event_mech, None) self.instr.write("RCVSLOWSRQ") self.instr.write("1") self.instr.write("SENDSLOWSRQ") try: t1 = time.time() while not handler.event_success: if (time.time() - t1) > 2: break time.sleep(0.1) finally: self.instr.disable_event(event_type, event_mech) self.instr.uninstall_handler( event_type, handler.handle_event, user_handle ) assert self.instr.session == handler.session.value assert self.compare_user_handle(handler.handle.contents, user_handle) assert handler.srq_success assert self.instr.read() == "1" finally: ctwrapper.WRAP_HANDLER = True class LockableMessagedBasedResourceTestCaseMixin(LockableResourceTestCaseMixin): """Mixing for message based resources supporting locking.""" def test_shared_locking(self): """Test locking/unlocking a resource.""" instr2 = self.rm.open_resource(str(self.rname)) instr3 = self.rm.open_resource(str(self.rname)) key = self.instr.lock() instr2.lock(requested_key=key) assert self.instr.query("*IDN?") assert instr2.query("*IDN?") with pytest.raises(errors.VisaIOError): instr3.query("*IDN?") # Share the lock for a limited time with instr3.lock_context(requested_key=key) as key2: assert instr3.query("*IDN?") assert key == key2 # Stop sharing the lock instr2.unlock() with pytest.raises(errors.VisaIOError): instr2.query("*IDN?") with pytest.raises(errors.VisaIOError): instr3.query("*IDN?") self.instr.unlock() assert instr3.query("*IDN?") def test_exclusive_locking(self): """Test locking/unlocking a resource.""" instr2 = self.rm.open_resource(str(self.rname)) self.instr.lock_excl() with pytest.raises(errors.VisaIOError): instr2.query("*IDN?") self.instr.unlock() assert instr2.query("*IDN?") # Share the lock for a limited time with self.instr.lock_context(requested_key="exclusive") as key: assert key is None with pytest.raises(errors.VisaIOError): instr2.query("*IDN?") pyvisa-1.11.3/pyvisa/testsuite/keysight_assisted_tests/resource_utils.py000066400000000000000000000150731375165327600270720ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Common test case for all resources. """ import gc import logging import re from typing import Union import pytest from pyvisa import InvalidSession, ResourceManager from pyvisa.constants import InterfaceType, ResourceAttribute, StatusCode, Timeouts from pyvisa.resources.resource import Resource from pyvisa.rname import ResourceName from . import RESOURCE_ADDRESSES class ResourceTestCase: """Base test case for all resources.""" #: Type of resource being tested in this test case. #: See RESOURCE_ADDRESSES in the __init__.py file of this package for #: acceptable values RESOURCE_TYPE = "" #: Minimal timeout value accepted by the resource. When setting the timeout #: to Timeouts.immediate, Visa (Keysight at least) may actually use a #: different value depending on the values supported by the resource. MINIMAL_TIMEOUT: Union[int, Timeouts] = Timeouts.immediate def setup_method(self): """Create a resource using the address matching the type.""" name = RESOURCE_ADDRESSES[self.RESOURCE_TYPE] self.rname = ResourceName.from_string(name) self.rm = ResourceManager() self.instr = self.rm.open_resource(name) self.instr.clear() def teardown_method(self): """Close the resource at the end of the test.""" if self.instr: self.instr.close() if self.rm: self.rm.close() def test_lifecycle(self): """Test the lifecyle of a resource and the use as a context manager.""" assert self.instr.session is not None assert self.instr.visalib is not None assert self.instr.last_status == StatusCode.success self.instr.close() with pytest.raises(InvalidSession): self.instr.session with self.rm.open_resource(str(self.rname), read_termination="\0") as instr: assert len(self.rm.list_opened_resources()) == 1 assert instr.read_termination == "\0" assert len(self.rm.list_opened_resources()) == 0 def test_close_on_del(self, caplog): """Test the lifecyle of a resource and the use as a context manager.""" with caplog.at_level(logging.DEBUG): self.instr = None gc.collect() assert "- closing" in caplog.records[0].message assert "- is closed", caplog.output[-1].message def test_alias_bypassing(self): """Test that a resource that cannot normalize an alias keep the alias.""" instr = Resource(self.rm, "visa_alias") assert re.match(r".* at %s" % "visa_alias", str(instr)) def test_str(self): """Test the string representation of a resource.""" assert re.match(r".* at %s" % str(self.rname), str(self.instr)) self.instr.close() assert re.match(r".* at %s" % str(self.rname), str(self.instr)) def test_repr(self): """Test the repr of a resource.""" assert re.match(r"<.*\('%s'\)>" % str(self.rname), repr(self.instr)) self.instr.close() assert re.match(r"<.*\('%s'\)>" % str(self.rname), repr(self.instr)) def test_timeout(self): """Test setting the timeout attribute.""" self.instr.timeout = None assert self.instr.timeout == float("+inf") assert ( self.instr.get_visa_attribute(ResourceAttribute.timeout_value) == Timeouts.infinite ) self.instr.timeout = 0.1 assert self.instr.timeout == 1 assert ( self.instr.get_visa_attribute(ResourceAttribute.timeout_value) == self.MINIMAL_TIMEOUT ) self.instr.timeout = 10 assert self.instr.timeout == 10 assert self.instr.get_visa_attribute(ResourceAttribute.timeout_value) == 10 with pytest.raises(ValueError): self.instr.timeout = 10000000000 del self.instr.timeout assert self.instr.timeout == float("+inf") assert ( self.instr.get_visa_attribute(ResourceAttribute.timeout_value) == Timeouts.infinite ) def test_resource_info(self): """Test accessing the resource info.""" rinfo = self.instr.resource_info assert rinfo.interface_type == getattr( InterfaceType, self.rname.interface_type.lower() ) assert rinfo.interface_board_number == int(self.rname.board) assert rinfo.resource_class == self.rname.resource_class assert rinfo.resource_name == str(self.rname) def test_interface_type(self): """Test accessing the resource interface_type.""" assert self.instr.interface_type == getattr( InterfaceType, self.rname.interface_type.lower() ) def test_attribute_handling(self): """Test directly manipulating attributes ie not using descriptors. This should extended in subclasses to test a broader range of attributes. """ self.instr.set_visa_attribute(ResourceAttribute.timeout_value, 10) assert self.instr.get_visa_attribute(ResourceAttribute.timeout_value) == 10 assert self.instr.timeout == 10 self.instr.set_visa_attribute( ResourceAttribute.timeout_value, Timeouts.immediate ) assert ( self.instr.get_visa_attribute(ResourceAttribute.timeout_value) == self.MINIMAL_TIMEOUT ) assert self.instr.timeout == 1 self.instr.set_visa_attribute( ResourceAttribute.timeout_value, Timeouts.infinite ) assert ( self.instr.get_visa_attribute(ResourceAttribute.timeout_value) == Timeouts.infinite ) assert self.instr.timeout == float("+inf") class EventAwareResourceTestCaseMixin: """Mixing for resources supporting handling events.""" def test_wait_on_event(self): """Test waiting on a VISA event. Should be implemented on subclasses, since the way to generate the event may be dependent on the resource type. """ raise NotImplementedError() def test_managing_visa_handler(self): """Test using visa handlers. Should be implemented on subclasses, since the way to generate the event may be dependent on the resource type. """ raise NotImplementedError() class LockableResourceTestCaseMixin: """Mixing for resources supporting locking.""" def test_shared_locking(self): """Test locking/unlocking a resource.""" raise NotImplementedError() def test_exclusive_locking(self): """Test locking/unlocking a resource.""" raise NotImplementedError() pyvisa-1.11.3/pyvisa/testsuite/keysight_assisted_tests/test_resource_manager.py000066400000000000000000000230201375165327600303720ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Test the capabilities of the ResourceManager. """ import gc import logging import re import pytest from pyvisa import InvalidSession, ResourceManager, VisaIOError, errors from pyvisa.constants import AccessModes, InterfaceType, StatusCode from pyvisa.highlevel import VisaLibraryBase from pyvisa.rname import ResourceName from pyvisa.testsuite import BaseTestCase from . import RESOURCE_ADDRESSES, require_virtual_instr @require_virtual_instr class TestResourceManager: """Test the pyvisa ResourceManager.""" def setup_method(self): """Create a ResourceManager with the default backend library.""" self.rm = ResourceManager() def teardown_method(self): """Close the ResourceManager.""" if self.rm is not None: self.rm.close() del self.rm gc.collect() def test_lifecycle(self, caplog): """Test creation and closing of the resource manager.""" assert self.rm.session is not None assert self.rm.visalib is not None assert self.rm is self.rm.visalib.resource_manager assert not self.rm.list_opened_resources() assert self.rm.visalib is ResourceManager(self.rm.visalib).visalib with caplog.at_level(level=logging.DEBUG, logger="pyvisa"): self.rm.close() assert caplog.records with pytest.raises(InvalidSession): self.rm.session assert self.rm.visalib.resource_manager is None def test_cleanup_on_del(self, caplog): """Test that deleting the rm does clean the VISA session""" # The test seems to assert what it should even though the coverage report # seems wrong rm = self.rm self.rm = None with caplog.at_level(logging.DEBUG, logger="pyvisa"): del rm gc.collect() assert "Closing ResourceManager" in caplog.records[0].message def test_resource_manager_unicity(self): """Test the resource manager is unique per backend as expected.""" new_rm = ResourceManager() assert self.rm is new_rm assert self.rm.session == new_rm.session def test_str(self): """Test computing the string representation of the resource manager""" assert re.match(r"Resource Manager of .*", str(self.rm)) self.rm.close() assert re.match(r"Resource Manager of .*", str(self.rm)) def test_repr(self): """Test computing the repr of the resource manager""" assert re.match(r"\)>", repr(self.rm)) self.rm.close() assert re.match(r"\)>", repr(self.rm)) def test_last_status(self): """Test accessing the status of the last operation.""" assert self.rm.last_status == StatusCode.success # Access the generic last status through the visalib assert self.rm.last_status == self.rm.visalib.last_status # Test accessing the status for an invalid session with pytest.raises(errors.Error) as cm: self.rm.visalib.get_last_status_in_session("_nonexisting_") assert "The session" in cm.exconly() def test_list_resource(self): """Test listing the available resources.""" # Default settings resources = self.rm.list_resources() for v in (v for v in RESOURCE_ADDRESSES.values() if v.endswith("INSTR")): assert str(ResourceName.from_string(v)) in resources # All resources resources = self.rm.list_resources("?*") for v in RESOURCE_ADDRESSES.values(): assert str(ResourceName.from_string(v)) in resources def test_accessing_resource_infos(self): """Test accessing resource infos.""" rname = list(RESOURCE_ADDRESSES.values())[0] rinfo_ext = self.rm.resource_info(rname) rinfo = self.rm.resource_info(rname, extended=False) rname = ResourceName().from_string(rname) assert rinfo_ext.interface_type == getattr( InterfaceType, rname.interface_type.lower() ) assert rinfo_ext.interface_board_number == int(rname.board) assert rinfo_ext.resource_class == rname.resource_class assert rinfo_ext.resource_name == str(rname) assert rinfo.interface_type == getattr( InterfaceType, rname.interface_type.lower() ) assert rinfo.interface_board_number == int(rname.board) def test_listing_resource_infos(self): """Test listing resource infos.""" infos = self.rm.list_resources_info() for rname, rinfo_ext in infos.items(): rname = ResourceName().from_string(rname) assert rinfo_ext.interface_type == getattr( InterfaceType, rname.interface_type.lower() ) assert rinfo_ext.interface_board_number == int(rname.board) assert rinfo_ext.resource_class == rname.resource_class assert rinfo_ext.resource_name == str(rname) def test_opening_resource(self): """Test opening and closing resources.""" rname = list(RESOURCE_ADDRESSES.values())[0] rsc = self.rm.open_resource(rname, timeout=1234) # Check the resource is listed as opened and the attributes are right. assert rsc in self.rm.list_opened_resources() assert rsc.timeout == 1234 # Close the rm to check that we close all resources. self.rm.close() assert not self.rm.list_opened_resources() with pytest.raises(InvalidSession): rsc.session def test_opening_resource_bad_open_timeout(self): """Test opening a resource with a non integer open_timeout.""" rname = list(RESOURCE_ADDRESSES.values())[0] with pytest.raises(ValueError) as cm: self.rm.open_resource(rname, open_timeout="") assert "integer (or compatible type)" in str(cm.exconly()) def test_opening_resource_with_lock(self): """Test opening a locked resource""" rname = list(RESOURCE_ADDRESSES.values())[0] rsc = self.rm.open_resource(rname, access_mode=AccessModes.exclusive_lock) assert len(self.rm.list_opened_resources()) == 1 # Timeout when accessing a locked resource with pytest.raises(VisaIOError): self.rm.open_resource(rname, access_mode=AccessModes.exclusive_lock) assert len(self.rm.list_opened_resources()) == 1 # Success to access an unlocked resource. rsc.unlock() with self.rm.open_resource( rname, access_mode=AccessModes.exclusive_lock ) as rsc2: assert rsc.session != rsc2.session assert len(self.rm.list_opened_resources()) == 2 def test_opening_resource_specific_class(self): """Test opening a resource requesting a specific class.""" rname = list(RESOURCE_ADDRESSES.values())[0] with pytest.raises(TypeError): self.rm.open_resource(rname, resource_pyclass=object) assert len(self.rm.list_opened_resources()) == 0 def test_open_resource_unknown_resource_type(self, caplog): """Test opening a resource for which no registered class exist.""" rc = ResourceManager._resource_classes old = rc.copy() class FakeResource: def __init__(self, *args): raise RuntimeError() rc[(InterfaceType.unknown, "")] = FakeResource del rc[(InterfaceType.tcpip, "INSTR")] rm = ResourceManager() try: caplog.clear() with caplog.at_level(level=logging.DEBUG, logger="pyvisa"): with pytest.raises(RuntimeError): rm.open_resource("TCPIP::192.168.0.1::INSTR") assert caplog.records finally: ResourceManager._resource_classes = old def test_opening_resource_unknown_attribute(self): """Test opening a resource and attempting to set an unknown attr.""" rname = list(RESOURCE_ADDRESSES.values())[0] with pytest.raises(ValueError): self.rm.open_resource(rname, unknown_attribute=None) assert len(self.rm.list_opened_resources()) == 0 def test_get_instrument(self): """Check that we get the expected deprecation warning.""" rname = list(RESOURCE_ADDRESSES.values())[0] with pytest.warns(FutureWarning): self.rm.get_instrument(rname) @require_virtual_instr class TestResourceParsing(BaseTestCase): """Test parsing resources using the builtin mechanism and the VISA lib. Those tests require that the interface exist (at least in Keysight implementation) so we cannot test arbitrary interfaces (PXI for example). """ def setup_method(self): """Create a ResourceManager with the default backend library.""" self.rm = ResourceManager() def teardown_method(self): """Close the ResourceManager.""" del self.rm gc.collect() def test_parse_tcpip_instr(self): self._parse_test("TCPIP::192.168.200.200::INSTR") def test_parse_tcpip_socket(self): self._parse_test("TCPIP::192.168.200.200::7020::SOCKET") def _parse_test(self, rn): # Visa lib p = self.rm.visalib.parse_resource_extended(self.rm.session, rn) # Internal pb = VisaLibraryBase.parse_resource_extended( self.rm.visalib, self.rm.session, rn ) assert p == pb # Non-extended parsing # Visa lib p = self.rm.visalib.parse_resource(self.rm.session, rn) # Internal pb = VisaLibraryBase.parse_resource(self.rm.visalib, self.rm.session, rn) assert p == pb pyvisa-1.11.3/pyvisa/testsuite/keysight_assisted_tests/test_rname_filter2.py000066400000000000000000000031741375165327600276120ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Common test case for all message based resources. """ import logging from pyvisa import ResourceManager, rname from pyvisa.resources import Resource from .. import BaseTestCase from . import require_virtual_instr @require_virtual_instr class TestFilter2(BaseTestCase): def setup_method(self): """Create a ResourceManager with the default backend library.""" self.rm = ResourceManager() def teardown_method(self): """Close the ResourceManager.""" self.rm.close() def _test_filter2(self, expr, *correct): resources = self.rm.list_resources(expr.split("{")[0]) ok = tuple(resources[n] for n in correct) filtered = rname.filter2( resources, expr, lambda rsc: self.rm.open_resource(rsc) ) assert filtered == ok def test_filter2_optional_clause_with_connection(self, caplog, monkeypatch): self._test_filter2( "?*::INSTR{VI_ATTR_TERMCHAR_EN == 1 && VI_ATTR_TERMCHAR == 0}" ) # Linefeed \n is 10 self._test_filter2("TCPIP::?*::INSTR{VI_ATTR_TERMCHAR == 10}") # test handling error in the evaluation of the attribute def broken_get_visa_attribute(self, name): raise Exception() monkeypatch.setattr(Resource, "get_visa_attribute", broken_get_visa_attribute) # Using any other log level will cause the test to fail for no apparent # good reason caplog.clear() with caplog.at_level(logging.DEBUG, logger="pyvisa"): self._test_filter2("TCPIP::?*::INSTR{VI_ATTR_TERMCHAR == 10}") assert caplog.records pyvisa-1.11.3/pyvisa/testsuite/keysight_assisted_tests/test_shell.py000066400000000000000000000442131375165327600261670ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Test the shell. """ import os import time from contextlib import redirect_stdout from io import StringIO from subprocess import PIPE, Popen from threading import Event, Lock, Thread from pyvisa import constants, errors from pyvisa.resources import Resource from pyvisa.rname import to_canonical_name from pyvisa.shell import VisaShell from .. import BaseTestCase from . import ALIASES, RESOURCE_ADDRESSES, require_virtual_instr class SubprocessOutputPoller: """Continuously check the stdout of a subprocess.""" def __init__(self, process): super().__init__() self.process = process self._lines = [] self._lines_lock = Lock() self._last_seen = time.monotonic() self.data_ready = Event() self._polling_thread = Thread(target=self.poll_stdout) self._ready_thread = Thread(target=self.check_ready) # Start background threads self._polling_thread.start() self._ready_thread.start() def poll_stdout(self): """Continously read stdout and update the lines. When no new data arrive after 1s consider that the data are ready. """ for line in iter(self.process.stdout.readline, b""): with self._lines_lock: self._lines.append(line.rstrip()) self._last_seen = time.monotonic() def check_ready(self): """Check if we got complete data.""" while True: time.sleep(0.05) if self._lines and time.monotonic() - self._last_seen > 0.5: self.data_ready.set() if not self._polling_thread.is_alive(): break def get_lines(self): """Get the collected lines.""" with self._lines_lock: lines = self._lines self._lines = [] self.data_ready.clear() return lines def shutdown(self): """Wait for threads to die after the process is done.""" self._polling_thread.join() self._ready_thread.join() @require_virtual_instr class TestVisaShell(BaseTestCase): """Test the VISA shell.""" def setup_method(self): """Start the shell in a subprocess.""" os.environ["COVERAGE_PROCESS_START"] = ".coveragerc" self.shell = Popen(["pyvisa-shell"], stdin=PIPE, stdout=PIPE) self.reader = SubprocessOutputPoller(self.shell) self.reader.data_ready.wait(1) self.reader.get_lines() def open_resource(self): lines = self.communicate(f"open {list(RESOURCE_ADDRESSES.values())[0]}") assert b"has been opened." in lines[0] def communicate(self, msg): """Write a message on stdin and collect the answer.""" self.shell.stdin.write(msg.encode("ascii") + b"\n") self.shell.stdin.flush() self.reader.data_ready.wait(1) return self.reader.get_lines() def teardown_method(self): if self.shell: self.shell.stdin.write(b"exit\n") self.shell.stdin.flush() self.shell.stdin.close() self.shell.terminate() self.shell.wait(0.1) self.reader.shutdown() def test_complete_open(self): """Test providing auto-completion for open.""" shell = VisaShell() completions = shell.complete_open("TCPIP", 0, 0, 0) assert to_canonical_name(RESOURCE_ADDRESSES["TCPIP::INSTR"]) in completions # Test getting an alias from the completion completions = shell.complete_open("tcp", 0, 0, 0) assert "tcpip" in completions def test_list(self): """Test listing the connected resources.""" lines = self.communicate("list") msg = [] for i, rsc in enumerate(RESOURCE_ADDRESSES.values()): if not rsc.endswith("INSTR"): continue msg.append(f"({i:2d}) {to_canonical_name(rsc)}") if rsc in ALIASES: msg.append(f" alias: {ALIASES[rsc]}") print(lines, msg) for m in msg: assert any(m.encode("ascii") in line for line in lines) # TODO fix argument handling to allow filtering def test_list_handle_error(self): """Test handling an error in listing resources.""" shell = VisaShell() shell.resource_manager = None temp_stdout = StringIO() with redirect_stdout(temp_stdout): shell.do_list("") output = temp_stdout.getvalue() assert "no attribute" in output def test_open_no_args(self): """Test opening without any argument.""" lines = self.communicate("open") assert b"A resource name must be specified." in lines[0] def test_open_by_number(self): """Test opening based on the index of the resource.""" lines = self.communicate("open 0") assert b'Not a valid resource number. Use the command "list".' in lines[0] lines = self.communicate("list") lines = self.communicate("open 0") rsc = list(RESOURCE_ADDRESSES.values())[0] assert f"{to_canonical_name(rsc)} has been opened.".encode("ascii") in lines[0] lines = self.communicate("open 0") assert ( b"You can only open one resource at a time. " b"Please close the current one first." ) in lines[0] def test_open_by_address(self): """Test opening based on the resource address.""" rsc = list(RESOURCE_ADDRESSES.values())[0] lines = self.communicate(f"open {rsc}") assert f"{rsc} has been opened.".encode("ascii") in lines[0] def test_open_handle_exception(self): """Test handling an exception during opening.""" lines = self.communicate('open ""') assert b"VI_ERROR_INV_RSRC_NAME" in lines[0] def test_handle_double_open(self): """Test handling before closing resource.""" rsc = list(RESOURCE_ADDRESSES.values())[0] lines = self.communicate(f"open {rsc}") lines = self.communicate(f"open {rsc}") assert ( b"You can only open one resource at a time. " b"Please close the current one first." ) in lines[0] def test_command_on_closed_resource(self): """Test all the commands that cannot be run without opening a resource.""" for cmd in ("close", "write", "read", "query", "termchar", "timeout", "attr"): lines = self.communicate(cmd) assert b'There are no resources in use. Use the command "open".' in lines[0] def test_close(self): """Test closing a resource.""" rsc = list(RESOURCE_ADDRESSES.values())[0] lines = self.communicate(f"open {rsc}") assert b"has been opened." in lines[0] lines = self.communicate("close") assert b"The resource has been closed." in lines[0] lines = self.communicate(f"open {rsc}") assert b"has been opened." in lines[0] def test_close_handle_error(self): """Test handling an error while closing.""" shell = VisaShell() shell.current = True temp_stdout = StringIO() with redirect_stdout(temp_stdout): shell.do_close("") output = temp_stdout.getvalue() assert "no attribute" in output def test_query(self): """querying a value from the instrument.""" self.open_resource() lines = self.communicate("query *IDN?") assert b"Response:" in lines[0] def test_query_handle_error(self): """Test handling an error in query.""" shell = VisaShell() shell.current = True temp_stdout = StringIO() with redirect_stdout(temp_stdout): shell.do_query("") output = temp_stdout.getvalue() assert "no attribute" in output def test_read_write(self): """Test writing/reading values from the resource.""" self.open_resource() lines = self.communicate("write *IDN?") lines = self.communicate("read") assert b"Keysight " in lines[0] def test_read_handle_error(self): """Test handling an error in read.""" shell = VisaShell() shell.current = True temp_stdout = StringIO() with redirect_stdout(temp_stdout): shell.do_read("") output = temp_stdout.getvalue() assert "no attribute" in output def test_write_handle_error(self): """Test handling an error in write.""" shell = VisaShell() shell.current = True temp_stdout = StringIO() with redirect_stdout(temp_stdout): shell.do_write("") output = temp_stdout.getvalue() assert "no attribute" in output def test_timeout_get(self): """Test accessing the timeout.""" self.open_resource() lines = self.communicate("timeout") assert b"Timeout: " in lines[0] def test_timeout_get_handle_error(self): """Test handling an error in getting teh timeout.""" shell = VisaShell() shell.current = True temp_stdout = StringIO() with redirect_stdout(temp_stdout): shell.do_timeout("") output = temp_stdout.getvalue() assert "no attribute" in output def test_timeout_set(self): """Test setting the timeout.""" self.open_resource() lines = self.communicate("timeout 1000") assert b"Done" in lines[0] lines = self.communicate("timeout") assert b"Timeout: 1000ms" in lines[0] def test_timeout_set_handle_error(self): """Test handling an error in setting the timeout""" shell = VisaShell() shell.current = True temp_stdout = StringIO() with redirect_stdout(temp_stdout): shell.do_timeout("1000") output = temp_stdout.getvalue() assert "no attribute" in output def test_print_attr_list(self): """Test printing attribute list.""" class FalseResource: @classmethod def get_visa_attribute(cls, id): if id == constants.VI_ATTR_TMO_VALUE: raise errors.VisaIOError(constants.VI_ERROR_NSUP_ATTR) elif id == constants.VI_ATTR_INTF_NUM: raise Exception("Long text: aaaaaaaaaaaaaaaaaaaa") else: raise Exception("Test") FalseResource.visa_attributes_classes = Resource.visa_attributes_classes shell = VisaShell() shell.current = FalseResource temp_stdout = StringIO() with redirect_stdout(temp_stdout): shell.print_attribute_list() output = temp_stdout.getvalue() assert "Long text:..." in output def test_attr_no_args(self): """Test getting the list of attributes""" self.open_resource() lines = self.communicate("attr") assert b"VISA name" in lines[1] def test_attr_too_many_args(self): """Test handling wrong args to attr.""" self.open_resource() lines = self.communicate("attr 1 2 3") assert ( b"Invalid syntax, use `attr ` to get;" b" or `attr ` to set" in lines[0] ) def test_issue_in_getting_attr(self): """Test handling exception in getting an attribute.""" shell = VisaShell() shell.do_open(list(RESOURCE_ADDRESSES.values())[0]) def broken_get_visa_attribute(self, name=""): raise Exception("Exception") # Issue on VI_ old = Resource.get_visa_attribute Resource.get_visa_attribute = broken_get_visa_attribute try: temp_stdout = StringIO() with redirect_stdout(temp_stdout): try: shell.do_attr("VI_ATTR_TERMCHAR") finally: Resource.get_visa_attribute = old output = temp_stdout.getvalue() assert "Exception" in output finally: Resource.get_visa_attribute = old # Issue on aliased attr old = type(shell.current).allow_dma type(shell.current).allow_dma = property(broken_get_visa_attribute) try: temp_stdout = StringIO() with redirect_stdout(temp_stdout): shell.do_attr("allow_dma") output = temp_stdout.getvalue() assert "Exception" in output finally: type(shell.current).allow_dma = old def test_attr_get_set_by_VI_non_boolean(self): """Test getting/setting an attr using the VI_ name (int value)""" self.open_resource() msg = "attr VI_ATTR_TERMCHAR {}".format(ord("\r")) lines = self.communicate(msg) assert b"Done" in lines[0] lines = self.communicate("attr VI_ATTR_TERMCHAR") assert str(ord("\r")) in lines[0].decode("ascii") def test_attr_get_set_by_VI_boolean(self): """Test getting/setting an attr using the VI_ name (bool value)""" self.open_resource() for v in (False, True): msg = f"attr VI_ATTR_TERMCHAR_EN {v}" lines = self.communicate(msg) assert b"Done" in lines[0] lines = self.communicate("attr VI_ATTR_TERMCHAR_EN") assert str(int(v)).encode("ascii") in lines[0] def test_attr_get_by_VI_handle_error(self): """Test accessing an attr by an unknown VI name.""" self.open_resource() lines = self.communicate("attr VI_test") assert b"no attribute" in lines[0] def test_attr_get_by_name(self): """Test accessing an attr by Python name.""" self.open_resource() lines = self.communicate("attr allow_dma") assert b"True" in lines[0] or b"False" in lines[0] def test_attr_get_by_name_handle_error(self): """Test accessing an attr by an unknown Python name.""" self.open_resource() lines = self.communicate("attr test") assert b"no attribute" in lines[0] def test_attr_set_by_VI_handle_error_unknown_attr(self): """Test handling issue in setting VI attr which does not exist.""" self.open_resource() lines = self.communicate("attr VI_test test") assert b"no attribute" in lines[0] def test_attr_set_by_VI_handle_error_non_boolean(self): """Test handling issue in setting VI attr. (non boolean value)""" self.open_resource() msg = "attr VI_ATTR_TERMCHAR_EN Test" lines = self.communicate(msg) assert b"Error" in lines[0] def test_attr_set_by_VI_handle_error_non_interger(self): """Test handling issue in setting VI attr. (non integer value)""" self.open_resource() msg = "attr VI_ATTR_TERMCHAR Test" lines = self.communicate(msg) assert b"Error" in lines[0] def test_attr_set_by_VI_handle_error_wrong_value(self): """Test handling issue in setting VI attr by name. (wrong value)""" self.open_resource() msg = "attr VI_ATTR_TERMCHAR -1" lines = self.communicate(msg) assert b"VI_ERROR_NSUP_ATTR_STATE" in lines[0] def test_attr_set_by_name_handle_error(self): """Test handling attempt to set attr by name (which is not supported).""" self.open_resource() msg = "attr allow_dma Test" lines = self.communicate(msg) assert ( b"Setting Resource Attributes by python name is not yet " b"supported." in lines[0] ) def test_complete_attr(self): """Test providing auto-completion for attrs.""" shell = VisaShell() shell.do_open(list(RESOURCE_ADDRESSES.values())[0]) completions = shell.complete_attr("VI_ATTR_TERM", 0, 0, 0) assert "VI_ATTR_TERMCHAR" in completions assert "VI_ATTR_TERMCHAR_EN" in completions completions = shell.complete_attr("allow_d", 0, 0, 0) assert "allow_dma" in completions def test_termchar_get_handle_error(self): """Test handling error when getting the termchars.""" shell = VisaShell() shell.current = True temp_stdout = StringIO() with redirect_stdout(temp_stdout): shell.do_termchar("") output = temp_stdout.getvalue() assert "no attribute" in output def test_getting_termchar_absent_mapping(self): """Test getting a termchar that does not map to something with a representation.""" shell = VisaShell() shell.do_open(list(RESOURCE_ADDRESSES.values())[0]) shell.current.read_termination = "X" shell.current.write_termination = "Z" temp_stdout = StringIO() with redirect_stdout(temp_stdout): shell.do_termchar("") output = temp_stdout.getvalue() assert "Termchar read: X write: Z" == output.split("\n")[0] def test_termchar_get_set_both_identical(self): """Test setting both termchars to the same value.""" self.open_resource() lines = self.communicate("termchar CR") assert b"Done" in lines[0] lines = self.communicate("termchar") assert b"Termchar read: CR write: CR" in lines[0] def test_termchar_get_set_both_different(self): """Test setting both termchars to different values.""" self.open_resource() lines = self.communicate("termchar CR NUL") assert b"Done" in lines[0] lines = self.communicate("termchar") assert b"Termchar read: CR write: NUL" in lines[0] def test_termchar_set_too_many_args(self): """Test handling to many termchars to termchar.""" self.open_resource() lines = self.communicate("termchar 1 2 3") assert b"Invalid syntax" in lines[0] def test_termchar_set_handle_error_wrong_value(self): """Test handling wrong value in setting termchar.""" self.open_resource() lines = self.communicate("termchar tt") assert b"use CR, LF, CRLF, NUL or None to set termchar" in lines[0] def test_termchar_set_handle_error(self): """Test handling an error in setting the termchars.""" shell = VisaShell() shell.current = True temp_stdout = StringIO() with redirect_stdout(temp_stdout): shell.do_termchar("CR") output = temp_stdout.getvalue() assert "no attribute" in output def test_eof(self): """Test handling an EOF.""" shell = VisaShell() assert shell.do_EOF(None) pyvisa-1.11.3/pyvisa/testsuite/keysight_assisted_tests/test_tcpip_resources.py000066400000000000000000000104471375165327600302730ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Test the TCPIP based resources. """ import pytest from pyvisa import constants, errors from . import copy_func, require_virtual_instr from .messagebased_resource_utils import ( EventAwareMessagebasedResourceTestCaseMixin, LockableMessagedBasedResourceTestCaseMixin, MessagebasedResourceTestCase, ) @require_virtual_instr class TestTCPIPInstr( LockableMessagedBasedResourceTestCaseMixin, EventAwareMessagebasedResourceTestCaseMixin, MessagebasedResourceTestCase, ): """Test pyvisa against a TCPIP INSTR resource.""" #: Type of resource being tested in this test case. #: See RESOURCE_ADDRESSES in the __init__.py file of this package for #: acceptable values RESOURCE_TYPE = "TCPIP::INSTR" #: Minimal timeout value accepted by the resource. When setting the timeout #: to VI_TMO_IMMEDIATE, Visa (Keysight at least) may actually use a #: different value depending on the values supported by the resource. MINIMAL_TIMEOUT = 1 def test_io_prot_attr(self): """Test getting/setting the io prot attribute. We would need to spy on the transaction to ensure we are sending a string instead of using the lower level mechanism. """ try: self.instr.read_stb() # XXX note sure what is the actual issue here with pytest.raises(errors.VisaIOError): self.instr.set_visa_attribute( constants.VI_ATTR_IO_PROT, constants.IOProtocol.hs488 ) # self.instr.read_stb() # assert ( # self.instr.get_visa_attribute(constants.VI_ATTR_IO_PROT) # == constants.IOProtocol.hs488 # ) finally: self.instr.set_visa_attribute( constants.VI_ATTR_IO_PROT, constants.IOProtocol.normal ) @require_virtual_instr class TestTCPIPSocket(MessagebasedResourceTestCase): """Test pyvisa against a TCPIP SOCKET resource.""" #: Type of resource being tested in this test case. #: See RESOURCE_ADDRESSES in the __init__.py file of this package for #: acceptable values RESOURCE_TYPE = "TCPIP::SOCKET" #: Minimal timeout value accepted by the resource. When setting the timeout #: to VI_TMO_IMMEDIATE, Visa (Keysight at least) may actually use a #: different value depending on the values supported by the resource. MINIMAL_TIMEOUT = 1 # Copy functions since the marker is applied in-place test_write_raw_read_bytes = pytest.mark.xfail( copy_func(MessagebasedResourceTestCase.test_write_raw_read_bytes) ) test_write_raw_read_raw = pytest.mark.xfail( copy_func(MessagebasedResourceTestCase.test_write_raw_read_raw) ) test_write_read = pytest.mark.xfail( copy_func(MessagebasedResourceTestCase.test_write_read) ) test_write_ascii_values = pytest.mark.xfail( copy_func(MessagebasedResourceTestCase.test_write_ascii_values) ) test_write_binary_values = pytest.mark.xfail( copy_func(MessagebasedResourceTestCase.test_write_binary_values) ) test_read_ascii_values = pytest.mark.xfail( copy_func(MessagebasedResourceTestCase.test_read_ascii_values) ) test_read_binary_values = pytest.mark.xfail( copy_func(MessagebasedResourceTestCase.test_read_binary_values) ) test_read_query_binary_values_invalid_header = pytest.mark.xfail( copy_func( MessagebasedResourceTestCase.test_read_query_binary_values_invalid_header ) ) test_read_binary_values_unreported_length = pytest.mark.xfail( copy_func( MessagebasedResourceTestCase.test_read_binary_values_unreported_length ) ) test_delay_in_query_ascii = pytest.mark.xfail( copy_func(MessagebasedResourceTestCase.test_delay_in_query_ascii) ) test_instrument_wide_delay_in_query_binary = pytest.mark.xfail( copy_func( MessagebasedResourceTestCase.test_instrument_wide_delay_in_query_binary ) ) test_delay_args_in_query_binary = pytest.mark.xfail( copy_func(MessagebasedResourceTestCase.test_delay_args_in_query_binary) ) test_no_delay_args_in_query_binary = pytest.mark.xfail( copy_func(MessagebasedResourceTestCase.test_no_delay_args_in_query_binary) ) pyvisa-1.11.3/pyvisa/testsuite/keysight_assisted_tests/test_util.py000066400000000000000000000007641375165327600260400ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Test pyvisa utility functions that requires a VISA library to be tested. """ from pyvisa import util from pyvisa.testsuite import BaseTestCase class TestSystemDetailsAnalysis(BaseTestCase): """Test getting details about the VISA library architecture.""" def test_getting_system_details_with_backend(self): """Test getting the system details with the backend details.""" details = util.get_system_details(True) assert details["backends"] pyvisa-1.11.3/pyvisa/testsuite/test_attributes.py000066400000000000000000000122341375165327600222740ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Test attribute descriptors. """ import enum import pytest from pyvisa import constants from pyvisa.attributes import ( Attribute, AttrVI_ATTR_ASRL_BAUD, AttrVI_ATTR_INTF_INST_NAME, BooleanAttribute, CharAttribute, EnumAttribute, IntAttribute, RangeAttribute, ValuesAttribute, ) from . import BaseTestCase class FakeResource: """Fake resource to test attributes.""" def __init__(self, attr_id, attr_value): self.attr_id = attr_id self.attr_value = attr_value def get_visa_attribute(self, attr_id): if attr_id == self.attr_id: return self.attr_value else: raise ValueError() def set_visa_attribute(self, attr_id, value): if attr_id == self.attr_id: self.attr_value = value else: raise ValueError() def create_resource_cls( attribute_name, attribute_type, read=True, write=True, attrs={} ): """Create a new attribute class and a resource using it.""" attrs.update({"attribute_id": attribute_name, "read": read, "write": write}) attr_cls = type("CA", (attribute_type,), attrs) return type("FakeR", (FakeResource,), {"attr": attr_cls()}) class TestAttributeClasses(BaseTestCase): """Test the descriptors used to handle VISA attributes.""" def test_in_resource_method(self): """Test the in_resource class method.""" assert AttrVI_ATTR_INTF_INST_NAME.in_resource(object()) assert AttrVI_ATTR_ASRL_BAUD.in_resource( (constants.InterfaceType.asrl, "INSTR") ) assert not AttrVI_ATTR_ASRL_BAUD.in_resource(object()) def test_Attribute(self): """Test the base class Attribute.""" rc = create_resource_cls("attr_id", Attribute) r = rc("attr_id", 1) assert r.attr == 1 r.attr = 2 assert r.attr == 2 # Check we do pass the write ID r.attr_id = "dummy" with pytest.raises(ValueError): r.attr with pytest.raises(ValueError): r.attr = 2 # Un-readable attribute rc = create_resource_cls("attr_id", Attribute, read=False) r = rc("attr_id", 1) with pytest.raises(AttributeError): r.attr # Un-writable attribute rc = create_resource_cls("attr_id", Attribute, write=False) r = rc("attr_id", 1) with pytest.raises(AttributeError): r.attr = 1 def test_BooleanAttribute(self): """Test BooleanAttribute.""" rc = create_resource_cls("attr_id", BooleanAttribute) r = rc("attr_id", constants.VI_TRUE) assert r.attr is True r.attr = False assert r.attr is False assert r.attr_value == constants.VI_FALSE def test_CharAttribute(self): """Test CharAttribute.""" rc = create_resource_cls("attr_id", CharAttribute) r = rc("attr_id", ord("\n")) assert r.attr == "\n" r.attr = "\r" assert r.attr == "\r" assert r.attr_value == 13 def test_EnumAttribute(self): """Test EnumAttribute""" @enum.unique class E(enum.IntEnum): a = 1 b = 2 rc = create_resource_cls("attr_id", EnumAttribute, attrs={"enum_type": E}) r = rc("attr_id", 1) assert r.attr == E.a r.attr = E.b assert r.attr == E.b assert r.attr_value == 2 with pytest.raises(ValueError): r.attr = 3 with pytest.raises(ValueError): r.attr = "" def test_IntAttribute(self): """Test IntAttribute.""" rc = create_resource_cls("attr_id", IntAttribute) r = rc("attr_id", "1") assert r.attr == 1 def test_RangeAttribute(self): """Test RangeAttribute""" rc = create_resource_cls( "attr_id", RangeAttribute, attrs={"min_value": 0, "max_value": 2} ) r = rc("attr_id", 1) r.attr = 0 assert r.attr_value == 0 r.attr = 2 assert r.attr_value == 2 r.attr = 1 assert r.attr_value == 1 with pytest.raises(ValueError) as cm: r.attr = -1 assert "invalid value" in str(cm.exconly()) assert " or " not in str(cm.exconly()) with pytest.raises(ValueError) as cm: r.attr = 3 assert "invalid value" in str(cm.exconly()) assert " or " not in str(cm.exconly()) rc = create_resource_cls( "attr_id", RangeAttribute, attrs={"min_value": 0, "max_value": 2, "values": [10]}, ) r = rc("attr_id", 1) r.attr = 10 assert r.attr_value == 10 with pytest.raises(ValueError) as cm: r.attr = 3 assert "invalid value" in str(cm.exconly()) assert " or " in str(cm.exconly()) def test_ValuesAttribute(self): """Test ValuesAttribute""" rc = create_resource_cls("attr_id", ValuesAttribute, attrs={"values": [10, 20]}) r = rc("attr_id", 1) r.attr = 10 assert r.attr_value == 10 with pytest.raises(ValueError) as cm: r.attr = 3 assert "invalid value" in str(cm.exconly()) pyvisa-1.11.3/pyvisa/testsuite/test_cmd_line_tools.py000066400000000000000000000044331375165327600231020ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Test the behavior of the command line tools. """ import sys from subprocess import PIPE, Popen, run import pytest from pyvisa import util from . import BaseTestCase, require_visa_lib class TestCmdLineTools(BaseTestCase): """Test the cmd line tools functions and scripts.""" @require_visa_lib def test_visa_main(self): """Test the visa scripts. The script is deprecated and will be removed, when it does this should be removed too. """ result = run( ["python", "-m", "visa", "info"], stdout=PIPE, universal_newlines=True ) details = util.system_details_to_str(util.get_system_details()) print(result.stdout.strip()) print() print(details.strip()) # Path difference can lead to subtle differences in the backends # compare only the first lines. assert ( result.stdout.strip().split("\n")[:16] == details.strip().split("\n")[:16] ) with Popen(["python", "-m", "visa", "shell"], stdin=PIPE, stdout=PIPE) as p: stdout, _ = p.communicate(b"exit") assert b"Welcome to the VISA shell" in stdout def test_visa_main_argument_handling(self): """Test we reject invalid values in visa_main.""" from pyvisa.cmd_line_tools import visa_main old = sys.argv = ["python"] try: with pytest.raises(ValueError): visa_main("unknown") finally: sys.argv = old def test_visa_info(self): """Test the visa info command line tool.""" result = run("pyvisa-info", stdout=PIPE, universal_newlines=True) details = util.system_details_to_str(util.get_system_details()) # Path difference can lead to subtle differences in the backends # compare only the first lines. assert ( result.stdout.strip().split("\n")[:16] == details.strip().split("\n")[:16] ) # TODO test backend selection: this is not easy at all to assert @require_visa_lib def test_visa_shell(self): """Test the visa shell function.""" with Popen(["pyvisa-shell"], stdin=PIPE, stdout=PIPE) as p: stdout, stderr = p.communicate(b"exit") assert b"Welcome to the VISA shell" in stdout pyvisa-1.11.3/pyvisa/testsuite/test_constants.py000066400000000000000000000012131375165327600221150ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Test objects from constants. This file is part of PyVISA. :copyright: 2019-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ import pytest from pyvisa.constants import DataWidth from . import BaseTestCase class TestDataWidth(BaseTestCase): def test_conversion_from_literal(self): for v, e in zip( (8, 16, 32, 64), (DataWidth.bit_8, DataWidth.bit_16, DataWidth.bit_32, DataWidth.bit_64), ): assert DataWidth.from_literal(v) == e with pytest.raises(ValueError): DataWidth.from_literal(0) pyvisa-1.11.3/pyvisa/testsuite/test_env_var_handling.py000066400000000000000000000015121375165327600234070ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Test the reading of env vars. """ import os import sys from subprocess import PIPE, Popen from . import BaseTestCase class TestEnvVarHandling(BaseTestCase): """Test reading env vars""" def test_reading_wrap_handler(self): with Popen([sys.executable], stdin=PIPE, stdout=PIPE) as p: stdout, _ = p.communicate( b"from pyvisa import ctwrapper;print(ctwrapper.WRAP_HANDLER);exit()" ) assert b"True" == stdout.rstrip() env = os.environ.copy() env["PYVISA_WRAP_HANDLER"] = "0" with Popen([sys.executable], stdin=PIPE, stdout=PIPE, env=env) as p: stdout, _ = p.communicate( b"from pyvisa import ctwrapper;print(ctwrapper.WRAP_HANDLER);exit()" ) assert b"False" == stdout.rstrip() pyvisa-1.11.3/pyvisa/testsuite/test_errors.py000066400000000000000000000062411375165327600214230ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Test the handling of errors. """ import pickle from pyvisa import errors from pyvisa.testsuite import BaseTestCase class TestPicleUnpickle(BaseTestCase): def _test_pickle_unpickle(self, instance): pickled = pickle.dumps(instance) unpickled = pickle.loads(pickled) assert isinstance(unpickled, type(instance)) for attr in instance.__dict__: assert getattr(instance, attr) == getattr(unpickled, attr) def test_VisaIOError(self): self._test_pickle_unpickle(errors.VisaIOError(0)) def test_VisaIOWarning(self): self._test_pickle_unpickle(errors.VisaIOWarning(0)) def test_UnknownHandler(self): self._test_pickle_unpickle(errors.UnknownHandler(0, 0, 0)) def test_OSNotSupported(self): self._test_pickle_unpickle(errors.OSNotSupported("")) def test_InvalidBinaryFormat(self): self._test_pickle_unpickle(errors.InvalidBinaryFormat()) self._test_pickle_unpickle(errors.InvalidBinaryFormat("test")) def test_InvalidSession(self): self._test_pickle_unpickle(errors.InvalidSession()) class TestLibraryError(BaseTestCase): """Test the creation of Library errors.""" def test_from_exception_not_found(self): """Test handling a missing library file.""" exc = errors.LibraryError.from_exception( ValueError("visa.dll: image not found"), "visa.dll" ) assert "File not found" in str(exc) def test_from_exception_wrong_arch(self): """Test handling a library that report the wrong bitness.""" exc = errors.LibraryError.from_exception( ValueError("visa.dll: no suitable image found. no matching architecture"), "visa.dll", ) assert "No matching architecture" in str(exc) def test_from_exception_wrong_filetype(self): """Test handling a library file of the wrong type.""" exc = errors.LibraryError.from_exception( ValueError("visa.dll: no suitable image found."), "visa.dll" ) assert "Could not determine filetype" in str(exc) def test_from_exception_wrong_ELF(self): """Test handling a library file with a wrong ELF.""" exc = errors.LibraryError.from_exception( ValueError("visa.dll: wrong ELF class"), "visa.dll" ) assert "No matching architecture" in str(exc) def test_from_exception_random(self): """Test handling a library for which the error is not a usual one.""" exc = errors.LibraryError.from_exception(ValueError("visa.dll"), "visa.dll") assert "Error while accessing" in str(exc) def test_from_exception_decode_error(self): """Test handling an error that decode to string.""" class DummyExc(Exception): def __str__(self): raise b"\xFF".decode("ascii") exc = errors.LibraryError.from_exception( DummyExc("visa.dll: wrong ELF class"), "visa.dll" ) assert "Error while accessing visa.dll." == str(exc) # from_wrong_arch is exercised through the above tests. pyvisa-1.11.3/pyvisa/testsuite/test_event.py000066400000000000000000000027441375165327600212340ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Test events classes. This file is part of PyVISA. :copyright: 2019-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ import logging import pytest from pyvisa import constants, errors from pyvisa.events import Event from . import BaseTestCase class TestEvent(BaseTestCase): """Test Event functionalities.""" def setup_method(self): self.old = Event._event_classes.copy() def teardown_method(self): Event._event_classes = self.old def test_register(self): assert Event._event_classes[constants.EventType.clear] is Event def test_double_register_event_cls(self, caplog): class SubEvent(Event): pass with caplog.at_level(logging.DEBUG, logger="pyvisa"): Event.register(constants.EventType.clear)(SubEvent) assert caplog.records assert Event._event_classes[constants.EventType.clear] is SubEvent def test_register_event_cls_missing_attr(self): class SubEvent(Event): pass with pytest.raises(TypeError): Event.register(constants.EventType.exception)(SubEvent) assert Event._event_classes[constants.EventType.exception] is not SubEvent def test_event_context(self): event = Event(None, constants.EventType.clear, 1) assert event.context == 1 event.close() with pytest.raises(errors.InvalidSession): event.context pyvisa-1.11.3/pyvisa/testsuite/test_highlevel.py000066400000000000000000000210471375165327600220570ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Test highlevel functions not requiring an actual backend. """ import logging import os import sys import pytest from pyvisa import constants, highlevel, resources, rname from pyvisa.ctwrapper import IVIVisaLibrary from . import BaseTestCase class TestHighlevel(BaseTestCase): """Test highlevel functionalities.""" CHECK_NO_WARNING = False @pytest.mark.parametrize( "rsc_name, values", [ ("TCPIP::192.168.0.1::INSTR", (constants.InterfaceType.tcpip, 0, "INSTR")), ("TCPIP1::192.168.0.1::INSTR", (constants.InterfaceType.tcpip, 1, "INSTR")), ( "TCPIP::192.168.0.1::5000::SOCKET", (constants.InterfaceType.tcpip, 0, "SOCKET"), ), ( "TCPIP2::192.168.0.1::5000::SOCKET", (constants.InterfaceType.tcpip, 2, "SOCKET"), ), ("GPIB::1::INSTR", (constants.InterfaceType.gpib, 0, "INSTR")), ("GPIB::INTFC", (constants.InterfaceType.gpib, 0, "INTFC")), ("GPIB2::1::INSTR", (constants.InterfaceType.gpib, 2, "INSTR")), ("GPIB3::INTFC", (constants.InterfaceType.gpib, 3, "INTFC")), ( "USB1::0x1111::0x2222::0x4445::0::RAW", (constants.InterfaceType.usb, 1, "RAW"), ), ( "USB0::0x1112::0x2223::0x1234::0::INSTR", (constants.InterfaceType.usb, 0, "INSTR"), ), ("ASRL2::INSTR", (constants.InterfaceType.asrl, 2, "INSTR")), ("ASRL/dev/tty0::INSTR", (constants.InterfaceType.asrl, None, "INSTR")), ], ) def test_base_class_parse_resource(self, rsc_name, values): """Test the base class implementation of parse_resource.""" lib = highlevel.VisaLibraryBase("test") info, ret_code = lib.parse_resource(None, rsc_name) # interface_type interface_board_number resource_class resource_name alias for parsed, value in zip(info, values[:2] + (None, None, None)): assert parsed == value info, ret_code = lib.parse_resource_extended(None, rsc_name) # interface_type interface_board_number resource_class resource_name alias for parsed, value in zip( info, values + ( rname.to_canonical_name(rsc_name), None, ), ): assert parsed == value def test_base_class_parse_resource_error(self): """Test errors in the base class implementation of parse_resource.""" lib = highlevel.VisaLibraryBase("test") rsc_name = "UNKNOWN::1::INSTR" info, ret_code = lib.parse_resource(None, rsc_name) assert ret_code == constants.StatusCode.error_invalid_resource_name assert info[0] == constants.InterfaceType.unknown def test_specifying_path_open_visa_library(self, caplog): """Test handling a specified path in open_visa_library.""" with caplog.at_level(logging.DEBUG): with pytest.raises(Exception): highlevel.open_visa_library("non/existent/file") assert "Could not open VISA wrapper" in caplog.records[0].message assert "non/existent/file" in caplog.records[0].message def test_handling_error_in_opening_library(self, caplog): """Test handling errors when trying to open a Visa library.""" class FakeLibrary(highlevel.VisaLibraryBase): @classmethod def get_library_paths(cls): return ["oserror", "error"] def _init(self): if self.library_path == "oserror": raise OSError("oserror") else: raise Exception("error") with caplog.at_level(logging.DEBUG): with pytest.raises(OSError) as cm: FakeLibrary() assert "oserror" in caplog.records[0].message msg = str(cm.exconly()).split("\n") assert len(msg) == 3 assert "oserror" in msg[1] assert "error" in msg[2] def test_list_backends(self): """Test listing backends.""" highlevel._WRAPPERS.clear() path = os.path.join(os.path.dirname(__file__), "fake-extensions") sys.path.append(path) try: backends = highlevel.list_backends() finally: sys.path.remove(path) assert "ivi" in backends assert "test" in backends def test_get_wrapper_class(self): """Test retrieving a wrapper class.""" highlevel._WRAPPERS.clear() with pytest.warns(FutureWarning): highlevel.get_wrapper_class("ni") assert "ivi" in highlevel._WRAPPERS path = os.path.join(os.path.dirname(__file__), "fake-extensions") sys.path.append(path) try: highlevel.get_wrapper_class("test") finally: sys.path.remove(path) assert "test" in highlevel._WRAPPERS with pytest.raises(ValueError): highlevel.get_wrapper_class("dummy") def test_get_default_wrapper(self, caplog): """Test retrieving the default wrapper.""" old_lib = IVIVisaLibrary.get_library_paths old_wrap = highlevel.get_wrapper_class def no_visa_found(): return [] def visa_found(): return [""] def py_wrapper_class(backend): return True def no_py_wrapper_class(backend): raise ValueError() try: # No implementation found IVIVisaLibrary.get_library_paths = staticmethod(no_visa_found) highlevel.get_wrapper_class = no_py_wrapper_class with pytest.raises(ValueError) as exc: with caplog.at_level(logging.DEBUG): highlevel._get_default_wrapper() assert "VISA implementation" in exc.exconly() assert "IVI binary" in caplog.records[0].message assert "find pyvisa-py" in caplog.records[1].message caplog.clear() # Pyvisa-py found highlevel.get_wrapper_class = py_wrapper_class with caplog.at_level(logging.DEBUG): assert highlevel._get_default_wrapper() == "py" assert "IVI binary" in caplog.records[0].message assert "pyvisa-py is available" in caplog.records[1].message caplog.clear() # IVI visa found IVIVisaLibrary.get_library_paths = staticmethod(visa_found) with caplog.at_level(logging.DEBUG): assert highlevel._get_default_wrapper() == "ivi" assert "IVI implementation available" in caplog.records[0].message finally: IVIVisaLibrary.get_library_paths = old_lib highlevel.get_wrapper_class = no_py_wrapper_class = old_wrap def test_register_resource_class(self, caplog): """Test registering resource classes.""" old = highlevel.ResourceManager._resource_classes.copy() try: class SubTCPIP(resources.TCPIPInstrument): pass with caplog.at_level(logging.WARNING): highlevel.ResourceManager.register_resource_class( constants.InterfaceType.tcpip, "INSTR", SubTCPIP ) assert caplog.records assert ( highlevel.ResourceManager._resource_classes[ (constants.InterfaceType.tcpip, "INSTR") ] is SubTCPIP ) finally: highlevel.ResourceManager._resource_classes = old def test_register_resource_class_missing_attr(self): """Test registering resource classes.""" old = highlevel.ResourceManager._resource_classes.copy() try: with pytest.raises(TypeError): highlevel.ResourceManager.register_resource_class( constants.InterfaceType.tcpip, "INSTR", object ) assert ( highlevel.ResourceManager._resource_classes[ (constants.InterfaceType.tcpip, "INSTR") ] is not object ) finally: highlevel.ResourceManager._resource_classes = old def test_base_get_library_paths(self): """Test the base class implementation of get_library_paths.""" assert () == highlevel.VisaLibraryBase.get_library_paths() def test_base_get_debug_info(self): """Test the base class implementation of get_debug_info.""" assert len(highlevel.VisaLibraryBase.get_debug_info()) == 1 pyvisa-1.11.3/pyvisa/testsuite/test_logging_utilities.py000066400000000000000000000036371375165327600236360ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Test pyvisa utility functions that requires a VISA library to be tested. """ import logging from io import StringIO import pyvisa from pyvisa.testsuite import BaseTestCase class TestLoggingUtilities(BaseTestCase): """Test standard logging utilities for pyvisa.""" def teardown_method(self): for h in pyvisa.logger.handlers: if not isinstance(h, logging.NullHandler): pyvisa.logger.removeHandler(h) def test_log_to_stream(self): """Test redirecting the log to a custom stream.""" stream = StringIO() debug_stream = StringIO() pyvisa.log_to_stream(stream, level=logging.INFO) pyvisa.log_to_stream(debug_stream) pyvisa.logger.debug("debug test") pyvisa.logger.info("info test") assert "debug test" in debug_stream.getvalue() assert "debug test" not in stream.getvalue() assert "info test" in debug_stream.getvalue() assert "info test" in stream.getvalue() def test_log_to_screen(self): """Test redirecting the log to stderr. Capture of stderr seems unreliable so avoid it """ self._log_to_screen_helper(logging.DEBUG) def test_log_to_screen_custom_level(self): """Test redirecting the log to stdout.""" self._log_to_screen_helper(logging.INFO) def _log_to_screen_helper(self, level): class Faker: def __init__(self): self.args = None def log_to_stream(self, *args): self.args = args faker = Faker() try: old = pyvisa.log_to_stream pyvisa.log_to_stream = faker.log_to_stream if level != logging.DEBUG: pyvisa.log_to_screen(level) else: pyvisa.log_to_screen() finally: pyvisa.log_to_stream = old assert faker.args == (None, level) pyvisa-1.11.3/pyvisa/testsuite/test_rname.py000066400000000000000000000437251375165327600212210ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Test test the resource name parsing. """ import logging from dataclasses import dataclass import pytest from typing_extensions import ClassVar from pyvisa import constants, errors, rname from pyvisa.testsuite import BaseTestCase class TestInvalidResourceName(BaseTestCase): """Test the creation of InvalidResourceName errors.""" def test_bad_syntax(self): """Test creating a bad syntax error.""" e = rname.InvalidResourceName.bad_syntax("syntax", "resource") assert str(e) == "Could not parse 'resource'. The syntax is 'syntax'." e = rname.InvalidResourceName.bad_syntax("syntax", "resource", "ex") assert str(e) == "Could not parse 'resource'. The syntax is 'syntax' (ex)." def test_subclass_notfound(self): """Test creating a subclass not found error""" e = rname.InvalidResourceName.subclass_notfound("inter") assert str(e) == "Parser not found for: inter." e = rname.InvalidResourceName.subclass_notfound("inter", "resource") assert str(e) == "Could not parse 'resource'. Parser not found for: inter." def test_rc_notfound(self): """Test creating a resource not found error.""" e = rname.InvalidResourceName.rc_notfound("inter") assert str(e) == "Resource class for inter not provided and default not found." e = rname.InvalidResourceName.rc_notfound("inter", "resource") assert str(e) == ( "Could not parse 'resource'. " "Resource class for inter not provided and default not found." ) class TestRegisteringSubclass(BaseTestCase): """Test the validation of ResourceName subclass during registration.""" def test_handling_duplicate(self): """Test we reject class for existing interface_type and resource class.""" with pytest.raises(ValueError) as e: rname.register_subclass(rname.GPIBInstr) assert "Class already registered for" in e.exconly() def test_handling_duplicate_default(self): """Test we enforce the unicity of default resource class per interface.""" with pytest.raises(ValueError) as e: @dataclass class R(rname.ResourceName): interface_type: ClassVar[str] = "TCPIP" resource_class: ClassVar[str] = "HISLIP" is_rc_optional: ClassVar[bool] = True rname.register_subclass(R) assert "Default already specified for" in e.exconly() class TestResourceName(BaseTestCase): """Test error handling in ResourceName. This exercise creating a resource name from parts too which is hence not tested explicitely. """ def test_creation_from_string(self): """Test error handling when creating a name from a string.""" # No interface class registered with pytest.raises(rname.InvalidResourceName) as e: rname.ResourceName.from_string("RJ45::1") assert "unknown interface type" in e.exconly() # No default resource class registered with pytest.raises(rname.InvalidResourceName) as e: rname.ResourceName.from_string("PXI::1") assert "not provided and default not found" in e.exconly() # No resource class registered, this cannot really happen... try: rname._RESOURCE_CLASSES["GPIB"].add("RAW") with pytest.raises(rname.InvalidResourceName) as e: rname.ResourceName.from_string("GPIB::1::RAW") assert "Parser not found for:" in e.exconly() finally: rname._RESOURCE_CLASSES["GPIB"].remove("RAW") # Test handling less than required parts with pytest.raises(rname.InvalidResourceName) as e: rname.ResourceName.from_string("GPIB::INSTR") assert "not enough parts" in e.exconly() # Test handling more than possible parts with pytest.raises(rname.InvalidResourceName) as e: rname.ResourceName.from_string("GPIB1::1::1::1::INSTR") assert "too many parts" in e.exconly() # Test handling missing mandatory part with pytest.raises(rname.InvalidResourceName) as e: rname.ResourceName.from_string("GPIB::::INSTR") assert "The syntax is" in e.exconly() # Test handling no part situation with pytest.raises(rname.InvalidResourceName) as e: rname.ResourceName.from_string("ASRL") assert "The syntax is" in e.exconly() def test_creation_from_kwargs(self): """Test error handling when creating a name from a kwargs.""" # No interface class registered with pytest.raises(rname.InvalidResourceName) as e: rname.ResourceName.from_kwargs(interface_type="RJ45") assert "Unknown interface type:" in e.exconly() # No default resource class registered with pytest.raises(rname.InvalidResourceName) as e: rname.ResourceName.from_kwargs(interface_type="PXI", chassis_number="1") assert "not provided and default not found" in e.exconly() # No resource class registered with pytest.raises(rname.InvalidResourceName) as e: rname.ResourceName.from_kwargs( interface_type="GPIB", address=1, resource_class="RAW" ) assert "Parser not found for:" in e.exconly() # Test bad resource from kwargs with pytest.raises(rname.InvalidResourceName) as e: rname.ResourceName.from_kwargs( interface_type="GPIB", resource_class="INSTR" ) assert "required parameter" in e.exconly() # Test assembling from kwargs rn = rname.ResourceName.from_kwargs(interface_type="GPIB", primary_address="1") assert str(rn) == rname.to_canonical_name("GPIB::1") def test_accessing_interface_type(self): """Test converting the interface to a VISA constant""" types = constants.InterfaceType for it, itc in zip( ("ASRL", "USB", "GPIB", "TCPIP", "PXI", "VXI"), (types.asrl, types.usb, types.gpib, types.tcpip, types.pxi, types.vxi), ): rn = rname.ResourceName() rn.interface_type = it assert rn.interface_type_const == itc rn = rname.ResourceName() rn.interface_type = "none" assert rn.interface_type_const == constants.InterfaceType.unknown class TestParsers(BaseTestCase): def _parse_test(self, rn, **kwargs): p = rname.ResourceName.from_string(rn) r = dict( (k, getattr(p, k)) for k in p._fields + ("interface_type", "resource_class") ) r["canonical_resource_name"] = rname.assemble_canonical_name(**r) assert r == kwargs, rn # @unittest.expectedFailure # def test_asrl_ethernet(self): # self._parse_test('ASRL::1.2.3.4::2::INSTR', # interface_type='ASRL', # resource_class='INSTR', # port='2', # address='1.2.3.4') def test_asrl(self): self._parse_test( "ASRL1::INSTR", interface_type="ASRL", resource_class="INSTR", board="1", canonical_resource_name="ASRL1::INSTR", ) self._parse_test( "ASRL1", interface_type="ASRL", resource_class="INSTR", board="1", canonical_resource_name="ASRL1::INSTR", ) def test_gpib_instr(self): self._parse_test( "GPIB::1::1::INSTR", interface_type="GPIB", resource_class="INSTR", board="0", primary_address="1", secondary_address="1", canonical_resource_name="GPIB0::1::1::INSTR", ) self._parse_test( "GPIB::1::INSTR", interface_type="GPIB", resource_class="INSTR", board="0", primary_address="1", secondary_address="0", canonical_resource_name="GPIB0::1::0::INSTR", ) self._parse_test( "GPIB1::1::INSTR", interface_type="GPIB", resource_class="INSTR", board="1", primary_address="1", secondary_address="0", canonical_resource_name="GPIB1::1::0::INSTR", ) self._parse_test( "GPIB1::1", interface_type="GPIB", resource_class="INSTR", board="1", primary_address="1", secondary_address="0", canonical_resource_name="GPIB1::1::0::INSTR", ) def test_gpib_intf(self): self._parse_test( "GPIB::INTFC", interface_type="GPIB", resource_class="INTFC", board="0", canonical_resource_name="GPIB0::INTFC", ) self._parse_test( "GPIB3::INTFC", interface_type="GPIB", resource_class="INTFC", board="3", canonical_resource_name="GPIB3::INTFC", ) def test_tcpip_intr(self): self._parse_test( "TCPIP::192.168.134.102", interface_type="TCPIP", resource_class="INSTR", host_address="192.168.134.102", board="0", lan_device_name="inst0", canonical_resource_name="TCPIP0::192.168.134.102::inst0::INSTR", ) self._parse_test( "TCPIP::dev.company.com::INSTR", interface_type="TCPIP", resource_class="INSTR", host_address="dev.company.com", board="0", lan_device_name="inst0", canonical_resource_name="TCPIP0::dev.company.com::inst0::INSTR", ) self._parse_test( "TCPIP3::dev.company.com::inst3::INSTR", interface_type="TCPIP", resource_class="INSTR", host_address="dev.company.com", board="3", lan_device_name="inst3", canonical_resource_name="TCPIP3::dev.company.com::inst3::INSTR", ) self._parse_test( "TCPIP3::1.2.3.4::inst3::INSTR", interface_type="TCPIP", resource_class="INSTR", host_address="1.2.3.4", board="3", lan_device_name="inst3", canonical_resource_name="TCPIP3::1.2.3.4::inst3::INSTR", ) def test_tcpip_socket(self): self._parse_test( "TCPIP::1.2.3.4::999::SOCKET", interface_type="TCPIP", resource_class="SOCKET", host_address="1.2.3.4", board="0", port="999", canonical_resource_name="TCPIP0::1.2.3.4::999::SOCKET", ) self._parse_test( "TCPIP2::1.2.3.4::999::SOCKET", interface_type="TCPIP", resource_class="SOCKET", host_address="1.2.3.4", board="2", port="999", canonical_resource_name="TCPIP2::1.2.3.4::999::SOCKET", ) def test_usb_instr(self): self._parse_test( "USB::0x1234::125::A22-5::INSTR", interface_type="USB", resource_class="INSTR", manufacturer_id="0x1234", model_code="125", serial_number="A22-5", board="0", usb_interface_number="0", canonical_resource_name="USB0::0x1234::125::A22-5::0::INSTR", ) self._parse_test( "USB2::0x1234::125::A22-5::INSTR", interface_type="USB", resource_class="INSTR", manufacturer_id="0x1234", model_code="125", serial_number="A22-5", board="2", usb_interface_number="0", canonical_resource_name="USB2::0x1234::125::A22-5::0::INSTR", ) self._parse_test( "USB::0x1234::125::A22-5", interface_type="USB", resource_class="INSTR", manufacturer_id="0x1234", model_code="125", serial_number="A22-5", board="0", usb_interface_number="0", canonical_resource_name="USB0::0x1234::125::A22-5::0::INSTR", ) self._parse_test( "USB::0x1234::125::A22-5::3::INSTR", interface_type="USB", resource_class="INSTR", manufacturer_id="0x1234", model_code="125", serial_number="A22-5", board="0", usb_interface_number="3", canonical_resource_name="USB0::0x1234::125::A22-5::3::INSTR", ) self._parse_test( "USB2::0x1234::125::A22-5::3::INSTR", interface_type="USB", resource_class="INSTR", manufacturer_id="0x1234", model_code="125", serial_number="A22-5", board="2", usb_interface_number="3", canonical_resource_name="USB2::0x1234::125::A22-5::3::INSTR", ) self._parse_test( "USB1::0x1234::125::A22-5::3", interface_type="USB", resource_class="INSTR", manufacturer_id="0x1234", model_code="125", serial_number="A22-5", board="1", usb_interface_number="3", canonical_resource_name="USB1::0x1234::125::A22-5::3::INSTR", ) def test_usb_raw(self): self._parse_test( "USB::0x1234::125::A22-5::RAW", interface_type="USB", resource_class="RAW", manufacturer_id="0x1234", model_code="125", serial_number="A22-5", board="0", usb_interface_number="0", canonical_resource_name="USB0::0x1234::125::A22-5::0::RAW", ) self._parse_test( "USB2::0x1234::125::A22-5::RAW", interface_type="USB", resource_class="RAW", manufacturer_id="0x1234", model_code="125", serial_number="A22-5", board="2", usb_interface_number="0", canonical_resource_name="USB2::0x1234::125::A22-5::0::RAW", ) self._parse_test( "USB2::0x1234::125::A22-5::3::RAW", interface_type="USB", resource_class="RAW", manufacturer_id="0x1234", model_code="125", serial_number="A22-5", board="2", usb_interface_number="3", canonical_resource_name="USB2::0x1234::125::A22-5::3::RAW", ) class TestFilters(BaseTestCase): CHECK_NO_WARNING = False run_list = ( "GPIB0::8::INSTR", "TCPIP0::localhost:1111::inst0::INSTR", "ASRL1::INSTR", "USB1::0x1111::0x2222::0x4445::0::RAW", "USB0::0x1112::0x2223::0x1234::0::INSTR", "TCPIP0::192.168.0.1::inst1::INSTR", "TCPIP0::localhost::10001::SOCKET", "GPIB9::7::65535::INSTR", "ASRL11::INSTR", "ASRL2::INSTR", "GPIB::INTFC", "PXI::1::BACKPLANE", "PXI::MEMACC", "VXI::1::BACKPLANE", # should work without the one "VXI::1::INSTR", "VXI::SERVANT", ) def _test_filter(self, expr, *correct): ok = tuple(self.run_list[n] for n in correct) assert rname.filter(self.run_list, expr) == ok def _test_filter2(self, expr, *correct): class MockedResource(object): def get_visa_attribute(self, attr): if attr == "VI_test": return 1 else: raise ValueError() def close(self): pass ok = tuple(self.run_list[n] for n in correct) filtered = rname.filter2(self.run_list, expr, lambda x: MockedResource()) assert filtered == ok def test_filter(self, caplog): self._test_filter("?*::INSTR", 0, 1, 2, 4, 5, 7, 8, 9, 14) self._test_filter("GPIB?+INSTR", 0, 7) self._test_filter("GPIB[0-8]*::?*INSTR", 0) self._test_filter("GPIB[^0]::?*INSTR", 7) self._test_filter("ASRL1+::INSTR", 2, 8) self._test_filter("(GPIB|VXI)?*INSTR", 0, 7, 14) with caplog.at_level(logging.DEBUG): self._test_filter("?*{}", *tuple(range(len(self.run_list)))) assert ( "optional part of the query expression not supported." in caplog.records[0].message ) # Not sure why this is needed self._test_handler = None def test_filter2_no_optional_clause(self): self._test_filter2("?*::INSTR", 0, 1, 2, 4, 5, 7, 8, 9, 14) self._test_filter2("GPIB?+INSTR", 0, 7) self._test_filter2("GPIB[0-8]*::?*INSTR", 0) self._test_filter2("GPIB[^0]::?*INSTR", 7) self._test_filter2("ASRL1+::INSTR", 2, 8) self._test_filter2("(GPIB|VXI)?*INSTR", 0, 7, 14) def test_filter2_optional_clause_no_connection(self): self._test_filter2("?*::INSTR{!(VI_ATTR_INTF_NUM == 0)}", 2, 7, 8, 9) self._test_filter2('?*{VI_ATTR_MANF_ID == "0x1111"}', 3) self._test_filter2('?*{VI_ATTR_MODEL_CODE == "0x2223"}', 4) self._test_filter2('?*{VI_ATTR_USB_SERIAL_NUM == "0x1234"}', 4) self._test_filter2("?*{VI_ATTR_USB_INTFC_NUM == 0}", 4) self._test_filter2('?*{VI_ATTR_TCPIP_ADDR == "localhost"}', 6) self._test_filter2('?*{VI_ATTR_TCPIP_DEVICE_NAME == "inst1"}', 5) self._test_filter2("?*{VI_ATTR_TCPIP_PORT == 10001}", 6) self._test_filter2("?*{VI_ATTR_GPIB_PRIMARY_ADDR == 8}", 0) self._test_filter2("?*{VI_ATTR_GPIB_SECONDARY_ADDR == 0}", 0) self._test_filter2("?*{VI_ATTR_PXI_CHASSIS == 1}", 11) self._test_filter2("?*{VI_ATTR_MAINFRAME_LA == 1}", 13, 14) self._test_filter2("?*{VI_ATTR_MAINFRAME_LA == 1 && VI_test == 1}", 13, 14) def test_bad_filter(self): with pytest.raises(errors.VisaIOError) as e: rname.filter([], "?*(") assert "VI_ERROR_INV_EXPR" in e.exconly() def test_bad_filter2(self): with pytest.raises(errors.VisaIOError) as e: rname.filter2([], "?*{", lambda x: None) assert "VI_ERROR_INV_EXPR" in e.exconly() pyvisa-1.11.3/pyvisa/testsuite/test_util.py000066400000000000000000000554251375165327600210740ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Test pyvisa utility functions. """ import array import contextlib import logging import os import struct import subprocess import sys import tempfile from configparser import ConfigParser from functools import partial from io import StringIO import pytest from pyvisa import highlevel, util from pyvisa.ctwrapper import IVIVisaLibrary from pyvisa.testsuite import BaseTestCase try: import numpy as np # type: ignore except ImportError: np = None class TestConfigFile(BaseTestCase): """Test reading information from a user configuration file.""" def setup_method(self): # Skip if a real config file exists if any( os.path.isfile(p) for p in [ os.path.join(sys.prefix, "share", "pyvisa", ".pyvisarc"), os.path.join(os.path.expanduser("~"), ".pyvisarc"), ] ): self.skipTest(".pyvisarc file exists cannot properly test in this case") self.temp_dir = tempfile.TemporaryDirectory() os.makedirs(os.path.join(self.temp_dir.name, "share", "pyvisa")) self.config_path = os.path.join( self.temp_dir.name, "share", "pyvisa", ".pyvisarc" ) self._prefix = sys.prefix sys.prefix = self.temp_dir.name self._platform = sys.platform self._version_info = sys.version_info def teardown_method(self): self.temp_dir.cleanup() sys.prefix = self._prefix sys.platform = self._platform sys.version_info = self._version_info def test_reading_config_file(self): config = ConfigParser() config["Paths"] = {} config["Paths"]["visa library"] = "test" with open(self.config_path, "w") as f: config.write(f) assert util.read_user_library_path() == "test" def test_no_section(self, caplog): config = ConfigParser() with open(self.config_path, "w") as f: config.write(f) with caplog.at_level(level=logging.DEBUG): assert util.read_user_library_path() is None assert "NoOptionError or NoSectionError" in caplog.records[1].message def test_no_key(self, caplog): config = ConfigParser() config["Paths"] = {} with open(self.config_path, "w") as f: config.write(f) with caplog.at_level(level=logging.DEBUG): assert util.read_user_library_path() is None assert "NoOptionError or NoSectionError" in caplog.records[1].message def test_no_config_file(self, caplog): with caplog.at_level(level=logging.DEBUG): assert util.read_user_library_path() is None assert "No user defined" in caplog.records[0].message # --- Test reading dll_extra_paths. def test_reading_config_file_not_windows(self, caplog): sys.platform = "darwin" sys.version_info = (3, 8, 1) with caplog.at_level(level=logging.DEBUG): assert util.add_user_dll_extra_paths() is None assert "Not loading dll_extra_paths" in caplog.records[0].message def test_reading_config_file_old_python(self, caplog): sys.platform = "win32" sys.version_info = (3, 7, 1) with caplog.at_level(level=logging.DEBUG): assert util.add_user_dll_extra_paths() is None assert "Not loading dll_extra_paths" in caplog.records[0].message def test_reading_config_file_for_dll_extra_paths(self, monkeypatch): sys.platform = "win32" sys.version_info = (3, 8, 1) monkeypatch.setattr( os, "add_dll_directory", lambda *args, **kwargs: "", raising=False ) config = ConfigParser() config["Paths"] = {} config["Paths"]["dll_extra_paths"] = r"C:\Program Files;C:\Program Files (x86)" with open(self.config_path, "w") as f: config.write(f) assert util.add_user_dll_extra_paths() == [ r"C:\Program Files", r"C:\Program Files (x86)", ] def test_no_section_for_dll_extra_paths(self, monkeypatch, caplog): sys.platform = "win32" sys.version_info = (3, 8, 1) monkeypatch.setattr( os, "add_dll_directory", lambda *args, **kwargs: "", raising=False ) config = ConfigParser() with open(self.config_path, "w") as f: config.write(f) with caplog.at_level(level=logging.DEBUG): assert util.add_user_dll_extra_paths() is None assert "NoOptionError or NoSectionError" in caplog.records[1].message def test_no_key_for_dll_extra_paths(self, monkeypatch, caplog): sys.platform = "win32" sys.version_info = (3, 8, 1) monkeypatch.setattr( os, "add_dll_directory", lambda *args, **kwargs: "", raising=False ) config = ConfigParser() config["Paths"] = {} with open(self.config_path, "w") as f: config.write(f) with caplog.at_level(level=logging.DEBUG): assert util.add_user_dll_extra_paths() is None assert "NoOptionError or NoSectionError" in caplog.records[1].message def test_no_config_file_for_dll_extra_paths(self, monkeypatch, caplog): sys.platform = "win32" sys.version_info = (3, 8, 1) monkeypatch.setattr( os, "add_dll_directory", lambda *args, **kwargs: "", raising=False ) with caplog.at_level(level=logging.DEBUG): assert util.add_user_dll_extra_paths() is None assert "No user defined" in caplog.records[0].message class TestParser(BaseTestCase): def test_parse_binary(self): s = ( b"#A@\xe2\x8b<@\xe2\x8b<@\xe2\x8b<@\xe2\x8b<@\xde\x8b<@\xde\x8b<@" b"\xde\x8b<@\xde\x8b<@\xe0\x8b<@\xe0\x8b<@\xdc\x8b<@\xde\x8b<@" b"\xe2\x8b<@\xe0\x8b<" ) e = [ 0.01707566, 0.01707566, 0.01707566, 0.01707566, 0.01707375, 0.01707375, 0.01707375, 0.01707375, 0.01707470, 0.01707470, 0.01707280, 0.01707375, 0.01707566, 0.01707470, ] # Test handling indefinite length block p = util.from_ieee_block(s, datatype="f", is_big_endian=False) for a, b in zip(p, e): assert a == pytest.approx(b) # Test handling definite length block p = util.from_ieee_block(b"#214" + s[2:], datatype="f", is_big_endian=False) for a, b in zip(p, e): assert a == pytest.approx(b) p = util.from_hp_block( b"#A\x0e\x00" + s[2:], datatype="f", is_big_endian=False, container=partial(array.array, "f"), ) for a, b in zip(p, e): assert a == pytest.approx(b) def test_integer_ascii_block(self): values = list(range(99)) for fmt in "d": msg = "block=%s, fmt=%s" msg = msg % ("ascii", fmt) tb = lambda values: util.to_ascii_block(values, fmt, ",") fb = lambda block, cont: util.from_ascii_block(block, fmt, ",", cont) self.round_trip_block_conversion(values, tb, fb, msg) def test_non_integer_ascii_block(self): values = [val + 0.5 for val in range(99)] values = list(range(99)) for fmt in "fFeEgG": msg = "block=%s, fmt=%s" msg = msg % ("ascii", fmt) tb = lambda values: util.to_ascii_block(values, fmt, ",") fb = lambda block, cont: util.from_ascii_block(block, fmt, ",", cont) self.round_trip_block_conversion(values, tb, fb, msg) def test_invalid_string_converter(self): with pytest.raises(ValueError) as ex: util.to_ascii_block([1, 2], "m") assert "unsupported format character" in ex.exconly() with pytest.raises(ValueError) as ex: util.from_ascii_block("1,2,3", "m") assert "Invalid code for converter" in ex.exconly() def test_function_separator(self): values = list(range(99)) fmt = "d" msg = "block=ascii, fmt=%s" % fmt tb = lambda values: util.to_ascii_block(values, fmt, ":".join) fb = lambda block, cont: util.from_ascii_block( block, fmt, lambda s: s.split(":"), cont ) self.round_trip_block_conversion(values, tb, fb, msg) def test_function_converter(self): values = list(range(99)) msg = "block=ascii" tb = lambda values: util.to_ascii_block(values, str, ":".join) fb = lambda block, cont: util.from_ascii_block( block, int, lambda s: s.split(":"), cont ) self.round_trip_block_conversion(values, tb, fb, msg) def test_integer_binary_block(self): values = list(range(99)) for block, tb, fb in zip( ("ieee", "hp"), (util.to_ieee_block, util.to_hp_block), (util.from_ieee_block, util.from_hp_block), ): for fmt in "bBhHiIfd": for endi in (True, False): msg = "block=%s, fmt=%s, endianness=%s" msg = msg % (block, fmt, endi) tblock = lambda values: tb(values, fmt, endi) fblock = lambda block, cont: fb(block, fmt, endi, cont) self.round_trip_block_conversion(values, tblock, fblock, msg) def test_noninteger_binary_block(self): values = [val + 0.5 for val in range(99)] for block, tb, fb in zip( ("ieee", "hp"), (util.to_ieee_block, util.to_hp_block), (util.from_ieee_block, util.from_hp_block), ): for fmt in "fd": for endi in (True, False): msg = "block=%s, fmt=%s, endianness=%s" msg = msg % (block, fmt, endi) tblock = lambda values: bytearray(tb(values, fmt, endi)) fblock = lambda block, cont: fb(block, fmt, endi, cont) self.round_trip_block_conversion(values, tblock, fblock, msg) def test_bytes_binary_block(self): values = b"dbslbw cj saj \x00\x76" for block, tb, fb in zip( ("ieee", "hp"), (util.to_ieee_block, util.to_hp_block), (util.from_ieee_block, util.from_hp_block), ): for fmt in "sp": block = tb(values, datatype="s") print(block) rt = fb(block, datatype="s", container=bytes) assert values == rt def test_malformed_binary_block_header(self): values = list(range(10)) for header, tb, fb in zip( ("ieee", "hp"), (util.to_ieee_block, util.to_hp_block), (util.from_ieee_block, util.from_hp_block), ): block = tb(values, "h", False) bad_block = block[1:] with pytest.raises(ValueError) as e: fb(bad_block, "h", False, list) assert "(#" in e.exconly() def test_weird_binary_block_header(self): values = list(range(100)) for header, tb, fb in zip( ("ieee", "hp"), (util.to_ieee_block, util.to_hp_block), (util.from_ieee_block, util.from_hp_block), ): block = tb(values, "h", False) bad_block = block[1:] if header == "hp": index = bad_block.find(b"#") bad_block = bad_block[:index] + b"#A" + bad_block[index + 2 :] with pytest.warns(UserWarning): fb(bad_block, "h", False, list) def test_weird_binary_block_header_raise(self): values = list(range(100)) for header, tb, fb in zip( ("ieee", "hp"), (util.to_ieee_block, util.to_hp_block), (util.from_ieee_block, util.from_hp_block), ): block = tb(values, "h", False) bad_block = block[1:] if header == "hp": index = bad_block.find(b"#") bad_block = bad_block[:index] + b"#A" + bad_block[index + 2 :] parse = ( util.parse_ieee_block_header if header == "ieee" else partial(util.parse_hp_block_header, is_big_endian=False) ) with pytest.raises(RuntimeError): parse(bad_block, raise_on_late_block=True) parse(bad_block, length_before_block=1000) def test_binary_block_shorter_than_advertized(self): values = list(range(99)) for header, tb, fb in zip( ("ieee", "hp"), (util.to_ieee_block, util.to_hp_block), (util.from_ieee_block, util.from_hp_block), ): block = tb(values, "h", False) if header == "ieee": header_byte_number = int(block[1]) block = ( block[:2] + b"9" * header_byte_number + block[2 + header_byte_number :] ) else: block = block[:2] + b"\xff\xff\xff\xff" + block[2 + 4 :] with pytest.raises(ValueError) as e: fb(block, "h", False, list) assert "Binary data is incomplete" in e.exconly() def test_guessing_block_length(self): values = list(range(99)) for header, tb, fb in zip( ("ieee", "hp"), (util.to_ieee_block, util.to_hp_block), (util.from_ieee_block, util.from_hp_block), ): block = tb(values, "h", False) + b"\n" if header == "ieee": header_length = int(block[1:2].decode()) block = block[:2] + b"0" * header_length + block[2 + header_length :] else: block = block[:2] + b"\x00\x00\x00\x00" + block[2 + 4 :] assert fb(block, "h", False, list) == values def test_handling_malformed_binary(self): containers = (list, tuple) + ((np.array, np.ndarray) if np else ()) # Use this to generate malformed data which should in theory be # impossible class DumbBytes(bytes): def __len__(self): return 10 for container in containers: with pytest.raises(ValueError) as e: util.from_binary_block(DumbBytes(b"\x00\x00\x00"), container=container) assert ( "malformed" if container in (list, tuple) else "buffer" in e.exconly() ) def round_trip_block_conversion(self, values, to_block, from_block, msg): """Test that block conversion round trip as expected.""" containers = (list, tuple) + ((np.array,) if np else ()) for cont in containers: conv = cont(values) msg += ", container=%s" msg = msg % cont.__name__ try: block = to_block(conv) parsed = from_block(block, cont) except Exception as e: raise Exception(msg + "\n" + repr(e)) if np and cont in (np.array,): np.testing.assert_array_equal(conv, parsed, msg) else: assert conv == parsed, msg class TestSystemDetailsAnalysis(BaseTestCase): """Test getting the system details.""" def setup_method(self): self._unicode_size = sys.maxunicode def teardown_method(self): sys.maxunicode = self._unicode_size def test_getting_system_details(self): sys.maxunicode = 65535 path = os.path.join(os.path.dirname(__file__), "fake-extensions") sys.path.append(path) try: details = util.get_system_details(True) finally: sys.path.remove(path) assert details["backends"] assert details["unicode"] == "UCS2" sys.maxunicode = 1114111 details = util.get_system_details(False) assert not details["backends"] assert details["unicode"] == "UCS4" def test_get_debug_info(self): details = util.system_details_to_str(util.get_system_details()) assert util.get_debug_info(False) == details temp_stdout = StringIO() with contextlib.redirect_stdout(temp_stdout): util.get_debug_info() output = temp_stdout.getvalue() assert output.strip() == details.strip() def test_system_details_for_plugins(self): """Test reporting on plugins.""" def dummy_list_backends(): return ["test1", "test2", "test3", "test4"] def dummy_get_wrapper_class(backend): if backend == "test1": return IVIVisaLibrary elif backend == "test2": class BrokenBackend: @classmethod def get_debug_info(cls): raise Exception() return BrokenBackend elif backend == "test4": class WeirdBackend: @classmethod def get_debug_info(cls): return {"": {"": [object()]}} return WeirdBackend else: raise Exception() old_lb = highlevel.list_backends old_gwc = highlevel.get_wrapper_class highlevel.list_backends = dummy_list_backends highlevel.get_wrapper_class = dummy_get_wrapper_class try: details = util.get_system_details() finally: highlevel.list_backends = old_lb highlevel.get_wrapper_class = old_gwc assert "Could not instantiate" in details["backends"]["test3"][0] assert "Could not obtain" in details["backends"]["test2"][0] assert "Version" in details["backends"]["test1"] assert "" in details["backends"]["test4"] # Test converting the details to string 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: 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): """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) ) assert arch == a arch = util.get_shared_library_arch( os.path.join(dirname, "fakelib_good_unknown.dll") ) assert arch == "UNKNOWN" with pytest.raises(Exception) as e: util.get_shared_library_arch(os.path.join(dirname, "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")) assert "Not a PE executable" in e.exconly() def test_get_arch_windows(self, tmpdir): """Test identifying the computer architecture on windows.""" dirname = str(tmpdir) generate_fakelibs(dirname) platform = sys.platform sys.platform = "win32" try: for f, a in zip( ["_32", "_64", "_64_2", "_unknown"], [(32,), (64,), (64,), ()] ): print(f, a) path = os.path.join(dirname, "fakelib_good%s.dll" % f) lib = util.LibraryPath(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 @pytest.mark.skipif(sys.version_info < (3, 7), reason="Fails weirdly on Python 3.6") def test_get_arch_unix(self): """Test identifying the computer architecture on linux and Mac.""" platform = sys.platform run = subprocess.run try: def alt_run(*args, **kwargs): if platform.startswith("win"): kwargs["shell"] = True return run(["echo", args[0][1]], *args[1:], **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,)), ]: 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 def test_get_arch_unix_unreported(self): """Test identifying the computer architecture on an unknown platform.""" platform = sys.platform run = subprocess.run 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" finally: sys.platform = platform subprocess.run = run def test_get_arch_unknown(self): """Test identifying the computer architecture on an unknown platform.""" platform = sys.platform run = subprocess.run 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" finally: sys.platform = platform subprocess.run = run pyvisa-1.11.3/pyvisa/thirdparty/000077500000000000000000000000001375165327600166345ustar00rootroot00000000000000pyvisa-1.11.3/pyvisa/thirdparty/__init__.py000066400000000000000000000003521375165327600207450ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Third party libraries and modules bundled with PyVISA. This file is part of PyVISA. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ pyvisa-1.11.3/pyvisa/thirdparty/prettytable.py000066400000000000000000002006731375165327600215550ustar00rootroot00000000000000#!/usr/bin/env python # # Copyright (c) 2009-2014, Luke Maurits # All rights reserved. # With contributions from: # * Chris Clark # * Klein Stephane # * John Filleau # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # * The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import copy import csv import itertools import json import math import random import re import sys import textwrap import unicodedata import pkg_resources __version__ = "0.7.3.dev.43cdb910a6fbee396e1fceb76a7775fa7314ee1d" py3k = sys.version_info[0] >= 3 if py3k: unicode = str basestring = str itermap = map iterzip = zip uni_chr = chr from html.parser import HTMLParser from html import escape else: itermap = itertools.imap iterzip = itertools.izip uni_chr = unichr # noqa: F821 from HTMLParser import HTMLParser from cgi import escape # hrule styles FRAME = 0 ALL = 1 NONE = 2 HEADER = 3 # Table styles DEFAULT = 10 MSWORD_FRIENDLY = 11 PLAIN_COLUMNS = 12 MARKDOWN = 13 RANDOM = 20 _re = re.compile(r"\033\[[0-9;]*m") def _get_size(text): lines = text.split("\n") height = len(lines) width = max(_str_block_width(line) for line in lines) return (width, height) class PrettyTable(object): def __init__(self, field_names=None, **kwargs): """Return a new PrettyTable instance Arguments: encoding - Unicode encoding scheme used to decode any encoded input title - optional table title field_names - list or tuple of field names fields - list or tuple of field names to include in displays start - index of first data row to include in output end - index of last data row to include in output PLUS ONE (list slice style) header - print a header showing field names (True or False) header_style - stylisation to apply to field names in header ("cap", "title", "upper", "lower" or None) border - print a border around the table (True or False) hrules - controls printing of horizontal rules after rows. Allowed values: FRAME, HEADER, ALL, NONE vrules - controls printing of vertical rules between columns. Allowed values: FRAME, ALL, NONE int_format - controls formatting of integer data float_format - controls formatting of floating point data min_table_width - minimum desired table width, in characters max_table_width - maximum desired table width, in characters padding_width - number of spaces on either side of column data (only used if left and right paddings are None) left_padding_width - number of spaces on left hand side of column data right_padding_width - number of spaces on right hand side of column data vertical_char - single character string used to draw vertical lines horizontal_char - single character string used to draw horizontal lines junction_char - single character string used to draw line junctions sortby - name of field to sort rows by sort_key - sorting key function, applied to data points before sorting valign - default valign for each row (None, "t", "m" or "b") reversesort - True or False to sort in descending or ascending order oldsortslice - Slice rows before sorting in the "old style" """ self.encoding = kwargs.get("encoding", "UTF-8") # Data self._field_names = [] self._rows = [] self.align = {} self.valign = {} self.max_width = {} self.min_width = {} self.int_format = {} self.float_format = {} if field_names: self.field_names = field_names else: self._widths = [] # Options self._options = ( "title start end fields header border sortby reversesort " "sort_key attributes format hrules vrules".split() ) self._options.extend( "int_format float_format min_table_width max_table_width padding_width " "left_padding_width right_padding_width".split() ) self._options.extend( "vertical_char horizontal_char junction_char header_style valign xhtml " "print_empty oldsortslice".split() ) self._options.extend("align valign max_width min_width".split()) for option in self._options: if option in kwargs: self._validate_option(option, kwargs[option]) else: kwargs[option] = None self._title = kwargs["title"] or None self._start = kwargs["start"] or 0 self._end = kwargs["end"] or None self._fields = kwargs["fields"] or None if kwargs["header"] in (True, False): self._header = kwargs["header"] else: self._header = True self._header_style = kwargs["header_style"] or None if kwargs["border"] in (True, False): self._border = kwargs["border"] else: self._border = True self._hrules = kwargs["hrules"] or FRAME self._vrules = kwargs["vrules"] or ALL self._sortby = kwargs["sortby"] or None if kwargs["reversesort"] in (True, False): self._reversesort = kwargs["reversesort"] else: self._reversesort = False self._sort_key = kwargs["sort_key"] or (lambda x: x) # Column specific arguments, use property.setters self.align = kwargs["align"] or {} self.valign = kwargs["valign"] or {} self.max_width = kwargs["max_width"] or {} self.min_width = kwargs["min_width"] or {} self.int_format = kwargs["int_format"] or {} self.float_format = kwargs["float_format"] or {} self._min_table_width = kwargs["min_table_width"] or None self._max_table_width = kwargs["max_table_width"] or None self._padding_width = kwargs["padding_width"] or 1 self._left_padding_width = kwargs["left_padding_width"] or None self._right_padding_width = kwargs["right_padding_width"] or None self._vertical_char = kwargs["vertical_char"] or self._unicode("|") self._horizontal_char = kwargs["horizontal_char"] or self._unicode("-") self._junction_char = kwargs["junction_char"] or self._unicode("+") if kwargs["print_empty"] in (True, False): self._print_empty = kwargs["print_empty"] else: self._print_empty = True if kwargs["oldsortslice"] in (True, False): self._oldsortslice = kwargs["oldsortslice"] else: self._oldsortslice = False self._format = kwargs["format"] or False self._xhtml = kwargs["xhtml"] or False self._attributes = kwargs["attributes"] or {} def _unicode(self, value): if not isinstance(value, basestring): value = str(value) if not isinstance(value, unicode): value = unicode(value, self.encoding, "strict") return value def _justify(self, text, width, align): excess = width - _str_block_width(text) if align == "l": return text + excess * " " elif align == "r": return excess * " " + text else: if excess % 2: # Uneven padding # Put more space on right if text is of odd length... if _str_block_width(text) % 2: return (excess // 2) * " " + text + (excess // 2 + 1) * " " # and more space on left if text is of even length else: return (excess // 2 + 1) * " " + text + (excess // 2) * " " # Why distribute extra space this way? To match the behaviour of # the inbuilt str.center() method. else: # Equal padding on either side return (excess // 2) * " " + text + (excess // 2) * " " def __getattr__(self, name): if name == "rowcount": return len(self._rows) elif name == "colcount": if self._field_names: return len(self._field_names) elif self._rows: return len(self._rows[0]) else: return 0 else: raise AttributeError(name) def __getitem__(self, index): new = PrettyTable() new.field_names = self.field_names for attr in self._options: setattr(new, "_" + attr, getattr(self, "_" + attr)) setattr(new, "_align", getattr(self, "_align")) if isinstance(index, slice): for row in self._rows[index]: new.add_row(row) elif isinstance(index, int): new.add_row(self._rows[index]) else: raise Exception( "Index %s is invalid, must be an integer or slice" % str(index) ) return new if py3k: def __str__(self): return self.__unicode__() else: def __str__(self): return self.__unicode__().encode(self.encoding) def __unicode__(self): return self.get_string() ############################## # ATTRIBUTE VALIDATORS # ############################## # The method _validate_option is all that should be used elsewhere in the code base # to validate options. It will call the appropriate validation method for that # option. The individual validation methods should never need to be called directly # (although nothing bad will happen if they *are*). # Validation happens in TWO places. # Firstly, in the property setters defined in the ATTRIBUTE MANAGEMENT section. # Secondly, in the _get_options method, where keyword arguments are mixed with # persistent settings def _validate_option(self, option, val): if option in ("field_names"): self._validate_field_names(val) elif option in ( "start", "end", "max_width", "min_width", "min_table_width", "max_table_width", "padding_width", "left_padding_width", "right_padding_width", "format", ): self._validate_nonnegative_int(option, val) elif option in ("sortby"): self._validate_field_name(option, val) elif option in ("sort_key"): self._validate_function(option, val) elif option in ("hrules"): self._validate_hrules(option, val) elif option in ("vrules"): self._validate_vrules(option, val) elif option in ("fields"): self._validate_all_field_names(option, val) elif option in ( "header", "border", "reversesort", "xhtml", "print_empty", "oldsortslice", ): self._validate_true_or_false(option, val) elif option in ("header_style"): self._validate_header_style(val) elif option in ("int_format"): self._validate_int_format(option, val) elif option in ("float_format"): self._validate_float_format(option, val) elif option in ("vertical_char", "horizontal_char", "junction_char"): self._validate_single_char(option, val) elif option in ("attributes"): self._validate_attributes(option, val) def _validate_field_names(self, val): # Check for appropriate length if self._field_names: try: assert len(val) == len(self._field_names) except AssertionError: raise Exception( "Field name list has incorrect number of values, " "(actual) %d!=%d (expected)" % (len(val), len(self._field_names)) ) if self._rows: try: assert len(val) == len(self._rows[0]) except AssertionError: raise Exception( "Field name list has incorrect number of values, " "(actual) %d!=%d (expected)" % (len(val), len(self._rows[0])) ) # Check for uniqueness try: assert len(val) == len(set(val)) except AssertionError: raise Exception("Field names must be unique!") def _validate_header_style(self, val): try: assert val in ("cap", "title", "upper", "lower", None) except AssertionError: raise Exception( "Invalid header style, use cap, title, upper, lower or None!" ) def _validate_align(self, val): try: assert val in ["l", "c", "r"] except AssertionError: raise Exception("Alignment %s is invalid, use l, c or r!" % val) def _validate_valign(self, val): try: assert val in ["t", "m", "b", None] except AssertionError: raise Exception("Alignment %s is invalid, use t, m, b or None!" % val) def _validate_nonnegative_int(self, name, val): try: assert int(val) >= 0 except AssertionError: raise Exception( "Invalid value for {}: {}!".format(name, self._unicode(val)) ) def _validate_true_or_false(self, name, val): try: assert val in (True, False) except AssertionError: raise Exception("Invalid value for %s! Must be True or False." % name) def _validate_int_format(self, name, val): if val == "": return try: assert type(val) in (str, unicode) assert val.isdigit() except AssertionError: raise Exception( "Invalid value for %s! Must be an integer format string." % name ) def _validate_float_format(self, name, val): if val == "": return try: assert type(val) in (str, unicode) assert "." in val bits = val.split(".") assert len(bits) <= 2 assert bits[0] == "" or bits[0].isdigit() assert ( bits[1] == "" or bits[1].isdigit() or (bits[1][-1] == "f" and bits[1].rstrip("f").isdigit()) ) except AssertionError: raise Exception( "Invalid value for %s! Must be a float format string." % name ) def _validate_function(self, name, val): try: assert hasattr(val, "__call__") except AssertionError: raise Exception("Invalid value for %s! Must be a function." % name) def _validate_hrules(self, name, val): try: assert val in (ALL, FRAME, HEADER, NONE) except AssertionError: raise Exception( "Invalid value for %s! Must be ALL, FRAME, HEADER or NONE." % name ) def _validate_vrules(self, name, val): try: assert val in (ALL, FRAME, NONE) except AssertionError: raise Exception( "Invalid value for %s! Must be ALL, FRAME, or NONE." % name ) def _validate_field_name(self, name, val): try: assert (val in self._field_names) or (val is None) except AssertionError: raise Exception("Invalid field name: %s!" % val) def _validate_all_field_names(self, name, val): try: for x in val: self._validate_field_name(name, x) except AssertionError: raise Exception("fields must be a sequence of field names!") def _validate_single_char(self, name, val): try: assert _str_block_width(val) == 1 except AssertionError: raise Exception( "Invalid value for %s! Must be a string of length 1." % name ) def _validate_attributes(self, name, val): try: assert isinstance(val, dict) except AssertionError: raise Exception("attributes must be a dictionary of name/value pairs!") ############################## # ATTRIBUTE MANAGEMENT # ############################## @property def field_names(self): """List or tuple of field names""" return self._field_names @field_names.setter def field_names(self, val): val = [self._unicode(x) for x in val] self._validate_option("field_names", val) old_names = None if self._field_names: old_names = self._field_names[:] self._field_names = val if self._align and old_names: for old_name, new_name in zip(old_names, val): self._align[new_name] = self._align[old_name] for old_name in old_names: if old_name not in self._align: self._align.pop(old_name) else: self.align = "c" if self._valign and old_names: for old_name, new_name in zip(old_names, val): self._valign[new_name] = self._valign[old_name] for old_name in old_names: if old_name not in self._valign: self._valign.pop(old_name) else: self.valign = "t" @property def align(self): """Controls alignment of fields Arguments: align - alignment, one of "l", "c", or "r" """ return self._align @align.setter def align(self, val): if not self._field_names: self._align = {} elif val is None or (isinstance(val, dict) and len(val) == 0): for field in self._field_names: self._align[field] = "c" else: self._validate_align(val) for field in self._field_names: self._align[field] = val @property def valign(self): """Controls vertical alignment of fields Arguments: valign - vertical alignment, one of "t", "m", or "b" """ return self._valign @valign.setter def valign(self, val): if not self._field_names: self._valign = {} elif val is None or (isinstance(val, dict) and len(val) == 0): for field in self._field_names: self._valign[field] = "t" else: self._validate_valign(val) for field in self._field_names: self._valign[field] = val @property def max_width(self): """Controls maximum width of fields Arguments: max_width - maximum width integer""" return self._max_width @max_width.setter def max_width(self, val): if val is None or (isinstance(val, dict) and len(val) == 0): self._max_width = {} else: self._validate_option("max_width", val) for field in self._field_names: self._max_width[field] = val @property def min_width(self): """Controls minimum width of fields Arguments: min_width - minimum width integer""" return self._min_width @min_width.setter def min_width(self, val): if val is None or (isinstance(val, dict) and len(val) == 0): self._min_width = {} else: self._validate_option("min_width", val) for field in self._field_names: self._min_width[field] = val @property def min_table_width(self): return self._min_table_width @min_table_width.setter def min_table_width(self, val): self._validate_option("min_table_width", val) self._min_table_width = val @property def max_table_width(self): return self._max_table_width @max_table_width.setter def max_table_width(self, val): self._validate_option("max_table_width", val) self._max_table_width = val @property def fields(self): """List or tuple of field names to include in displays""" return self._fields @fields.setter def fields(self, val): self._validate_option("fields", val) self._fields = val @property def title(self): """Optional table title Arguments: title - table title""" return self._title @title.setter def title(self, val): self._title = self._unicode(val) @property def start(self): """Start index of the range of rows to print Arguments: start - index of first data row to include in output""" return self._start @start.setter def start(self, val): self._validate_option("start", val) self._start = val @property def end(self): """End index of the range of rows to print Arguments: end - index of last data row to include in output PLUS ONE (list slice style)""" return self._end @end.setter def end(self, val): self._validate_option("end", val) self._end = val @property def sortby(self): """Name of field by which to sort rows Arguments: sortby - field name to sort by""" return self._sortby @sortby.setter def sortby(self, val): self._validate_option("sortby", val) self._sortby = val @property def reversesort(self): """Controls direction of sorting (ascending vs descending) Arguments: reveresort - set to True to sort by descending order, or False to sort by ascending order""" return self._reversesort @reversesort.setter def reversesort(self, val): self._validate_option("reversesort", val) self._reversesort = val @property def sort_key(self): """Sorting key function, applied to data points before sorting Arguments: sort_key - a function which takes one argument and returns something to be sorted""" return self._sort_key @sort_key.setter def sort_key(self, val): self._validate_option("sort_key", val) self._sort_key = val @property def header(self): """Controls printing of table header with field names Arguments: header - print a header showing field names (True or False)""" return self._header @header.setter def header(self, val): self._validate_option("header", val) self._header = val @property def header_style(self): """Controls stylisation applied to field names in header Arguments: header_style - stylisation to apply to field names in header ("cap", "title", "upper", "lower" or None)""" return self._header_style @header_style.setter def header_style(self, val): self._validate_header_style(val) self._header_style = val @property def border(self): """Controls printing of border around table Arguments: border - print a border around the table (True or False)""" return self._border @border.setter def border(self, val): self._validate_option("border", val) self._border = val @property def hrules(self): """Controls printing of horizontal rules after rows Arguments: hrules - horizontal rules style. Allowed values: FRAME, ALL, HEADER, NONE""" return self._hrules @hrules.setter def hrules(self, val): self._validate_option("hrules", val) self._hrules = val @property def vrules(self): """Controls printing of vertical rules between columns Arguments: vrules - vertical rules style. Allowed values: FRAME, ALL, NONE""" return self._vrules @vrules.setter def vrules(self, val): self._validate_option("vrules", val) self._vrules = val @property def int_format(self): """Controls formatting of integer data Arguments: int_format - integer format string""" return self._int_format @int_format.setter def int_format(self, val): if val is None or (isinstance(val, dict) and len(val) == 0): self._int_format = {} else: self._validate_option("int_format", val) for field in self._field_names: self._int_format[field] = val @property def float_format(self): """Controls formatting of floating point data Arguments: float_format - floating point format string""" return self._float_format @float_format.setter def float_format(self, val): if val is None or (isinstance(val, dict) and len(val) == 0): self._float_format = {} else: self._validate_option("float_format", val) for field in self._field_names: self._float_format[field] = val @property def padding_width(self): """The number of empty spaces between a column's edge and its content Arguments: padding_width - number of spaces, must be a positive integer""" return self._padding_width @padding_width.setter def padding_width(self, val): self._validate_option("padding_width", val) self._padding_width = val @property def left_padding_width(self): """The number of empty spaces between a column's left edge and its content Arguments: left_padding - number of spaces, must be a positive integer""" return self._left_padding_width @left_padding_width.setter def left_padding_width(self, val): self._validate_option("left_padding_width", val) self._left_padding_width = val @property def right_padding_width(self): """The number of empty spaces between a column's right edge and its content Arguments: right_padding - number of spaces, must be a positive integer""" return self._right_padding_width @right_padding_width.setter def right_padding_width(self, val): self._validate_option("right_padding_width", val) self._right_padding_width = val @property def vertical_char(self): """The charcter used when printing table borders to draw vertical lines Arguments: vertical_char - single character string used to draw vertical lines""" return self._vertical_char @vertical_char.setter def vertical_char(self, val): val = self._unicode(val) self._validate_option("vertical_char", val) self._vertical_char = val @property def horizontal_char(self): """The charcter used when printing table borders to draw horizontal lines Arguments: horizontal_char - single character string used to draw horizontal lines""" return self._horizontal_char @horizontal_char.setter def horizontal_char(self, val): val = self._unicode(val) self._validate_option("horizontal_char", val) self._horizontal_char = val @property def junction_char(self): """The charcter used when printing table borders to draw line junctions Arguments: junction_char - single character string used to draw line junctions""" return self._junction_char @junction_char.setter def junction_char(self, val): val = self._unicode(val) self._validate_option("vertical_char", val) self._junction_char = val @property def format(self): """Controls whether or not HTML tables are formatted to match styling options Arguments: format - True or False""" return self._format @format.setter def format(self, val): self._validate_option("format", val) self._format = val @property def print_empty(self): """Controls whether or not empty tables produce a header and frame or just an empty string Arguments: print_empty - True or False""" return self._print_empty @print_empty.setter def print_empty(self, val): self._validate_option("print_empty", val) self._print_empty = val @property def attributes(self): """A dictionary of HTML attribute name/value pairs to be included in the tag when printing HTML Arguments: attributes - dictionary of attributes""" return self._attributes @attributes.setter def attributes(self, val): self._validate_option("attributes", val) self._attributes = val @property def oldsortslice(self): """ oldsortslice - Slice rows before sorting in the "old style" """ return self._oldsortslice @oldsortslice.setter def oldsortslice(self, val): self._validate_option("oldsortslice", val) self._oldsortslice = val ############################## # OPTION MIXER # ############################## def _get_options(self, kwargs): options = {} for option in self._options: if option in kwargs: self._validate_option(option, kwargs[option]) options[option] = kwargs[option] else: options[option] = getattr(self, "_" + option) return options ############################## # PRESET STYLE LOGIC # ############################## def set_style(self, style): if style == DEFAULT: self._set_default_style() elif style == MSWORD_FRIENDLY: self._set_msword_style() elif style == PLAIN_COLUMNS: self._set_columns_style() elif style == MARKDOWN: self._set_markdown_style() elif style == RANDOM: self._set_random_style() else: raise Exception("Invalid pre-set style!") def _set_markdown_style(self): self.header = True self.border = True self._hrules = None self.padding_width = 1 self.left_padding_width = 1 self.right_padding_width = 1 self.vertical_char = "|" self.junction_char = "|" def _set_default_style(self): self.header = True self.border = True self._hrules = FRAME self._vrules = ALL self.padding_width = 1 self.left_padding_width = 1 self.right_padding_width = 1 self.vertical_char = "|" self.horizontal_char = "-" self.junction_char = "+" def _set_msword_style(self): self.header = True self.border = True self._hrules = NONE self.padding_width = 1 self.left_padding_width = 1 self.right_padding_width = 1 self.vertical_char = "|" def _set_columns_style(self): self.header = True self.border = False self.padding_width = 1 self.left_padding_width = 0 self.right_padding_width = 8 def _set_random_style(self): # Just for fun! self.header = random.choice((True, False)) self.border = random.choice((True, False)) self._hrules = random.choice((ALL, FRAME, HEADER, NONE)) self._vrules = random.choice((ALL, FRAME, NONE)) self.left_padding_width = random.randint(0, 5) self.right_padding_width = random.randint(0, 5) self.vertical_char = random.choice(r"~!@#$%^&*()_+|-=\{}[];':\",./;<>?") self.horizontal_char = random.choice(r"~!@#$%^&*()_+|-=\{}[];':\",./;<>?") self.junction_char = random.choice(r"~!@#$%^&*()_+|-=\{}[];':\",./;<>?") ############################## # DATA INPUT METHODS # ############################## def add_row(self, row): """Add a row to the table Arguments: row - row of data, should be a list with as many elements as the table has fields""" if self._field_names and len(row) != len(self._field_names): raise Exception( "Row has incorrect number of values, (actual) %d!=%d (expected)" % (len(row), len(self._field_names)) ) if not self._field_names: self.field_names = [("Field %d" % (n + 1)) for n in range(0, len(row))] self._rows.append(list(row)) def del_row(self, row_index): """Delete a row to the table Arguments: row_index - The index of the row you want to delete. Indexing starts at 0.""" if row_index > len(self._rows) - 1: raise Exception( "Cant delete row at index %d, table only has %d rows!" % (row_index, len(self._rows)) ) del self._rows[row_index] def add_column(self, fieldname, column, align="c", valign="t"): """Add a column to the table. Arguments: fieldname - name of the field to contain the new column of data column - column of data, should be a list with as many elements as the table has rows align - desired alignment for this column - "l" for left, "c" for centre and "r" for right valign - desired vertical alignment for new columns - "t" for top, "m" for middle and "b" for bottom""" if len(self._rows) in (0, len(column)): self._validate_align(align) self._validate_valign(valign) self._field_names.append(fieldname) self._align[fieldname] = align self._valign[fieldname] = valign for i in range(0, len(column)): if len(self._rows) < i + 1: self._rows.append([]) self._rows[i].append(column[i]) else: raise Exception( "Column length %d does not match number of rows %d!" % (len(column), len(self._rows)) ) def clear_rows(self): """Delete all rows from the table but keep the current field names""" self._rows = [] def clear(self): """Delete all rows and field names from the table, maintaining nothing but styling options""" self._rows = [] self._field_names = [] self._widths = [] ############################## # MISC PUBLIC METHODS # ############################## def copy(self): return copy.deepcopy(self) ############################## # MISC PRIVATE METHODS # ############################## def _format_value(self, field, value): if isinstance(value, int) and field in self._int_format: value = self._unicode(("%%%sd" % self._int_format[field]) % value) elif isinstance(value, float) and field in self._float_format: value = self._unicode(("%%%sf" % self._float_format[field]) % value) return self._unicode(value) def _compute_table_width(self, options): table_width = 2 if options["vrules"] in (FRAME, ALL) else 0 per_col_padding = sum(self._get_padding_widths(options)) for index, fieldname in enumerate(self.field_names): if not options["fields"] or ( options["fields"] and fieldname in options["fields"] ): table_width += self._widths[index] + per_col_padding return table_width def _compute_widths(self, rows, options): if options["header"]: widths = [_get_size(field)[0] for field in self._field_names] else: widths = len(self.field_names) * [0] for row in rows: for index, value in enumerate(row): fieldname = self.field_names[index] if fieldname in self.max_width: widths[index] = max( widths[index], min(_get_size(value)[0], self.max_width[fieldname]), ) else: widths[index] = max(widths[index], _get_size(value)[0]) if fieldname in self.min_width: widths[index] = max(widths[index], self.min_width[fieldname]) self._widths = widths # Are we exceeding max_table_width? if self._max_table_width: table_width = self._compute_table_width(options) if table_width > self._max_table_width: # Shrink widths in proportion scale = 1.0 * self._max_table_width / table_width widths = [int(math.floor(w * scale)) for w in widths] self._widths = widths # Are we under min_table_width or title width? if self._min_table_width or options["title"]: if options["title"]: title_width = len(options["title"]) + sum( self._get_padding_widths(options) ) if options["vrules"] in (FRAME, ALL): title_width += 2 else: title_width = 0 min_table_width = self.min_table_width or 0 min_width = max(title_width, min_table_width) table_width = self._compute_table_width(options) if table_width < min_width: # Grow widths in proportion scale = 1.0 * min_width / table_width widths = [int(math.ceil(w * scale)) for w in widths] self._widths = widths def _get_padding_widths(self, options): if options["left_padding_width"] is not None: lpad = options["left_padding_width"] else: lpad = options["padding_width"] if options["right_padding_width"] is not None: rpad = options["right_padding_width"] else: rpad = options["padding_width"] return lpad, rpad def _get_rows(self, options): """Return only those data rows that should be printed, based on slicing and sorting. Arguments: options - dictionary of option settings.""" if options["oldsortslice"]: rows = copy.deepcopy(self._rows[options["start"] : options["end"]]) else: rows = copy.deepcopy(self._rows) # Sort if options["sortby"]: sortindex = self._field_names.index(options["sortby"]) # Decorate rows = [[row[sortindex]] + row for row in rows] # Sort rows.sort(reverse=options["reversesort"], key=options["sort_key"]) # Undecorate rows = [row[1:] for row in rows] # Slice if necessary if not options["oldsortslice"]: rows = rows[options["start"] : options["end"]] return rows def _format_row(self, row, options): return [ self._format_value(field, value) for (field, value) in zip(self._field_names, row) ] def _format_rows(self, rows, options): return [self._format_row(row, options) for row in rows] ############################## # PLAIN TEXT STRING METHODS # ############################## def get_string(self, **kwargs): """Return string representation of table in current state. Arguments: title - optional table title start - index of first data row to include in output end - index of last data row to include in output PLUS ONE (list slice style) fields - names of fields (columns) to include header - print a header showing field names (True or False) border - print a border around the table (True or False) hrules - controls printing of horizontal rules after rows. Allowed values: ALL, FRAME, HEADER, NONE vrules - controls printing of vertical rules between columns. Allowed values: FRAME, ALL, NONE int_format - controls formatting of integer data float_format - controls formatting of floating point data padding_width - number of spaces on either side of column data (only used if left and right paddings are None) left_padding_width - number of spaces on left hand side of column data right_padding_width - number of spaces on right hand side of column data vertical_char - single character string used to draw vertical lines horizontal_char - single character string used to draw horizontal lines junction_char - single character string used to draw line junctions sortby - name of field to sort rows by sort_key - sorting key function, applied to data points before sorting reversesort - True or False to sort in descending or ascending order print empty - if True, stringify just the header for an empty table, if False return an empty string""" options = self._get_options(kwargs) lines = [] # Don't think too hard about an empty table # Is this the desired behaviour? Maybe we should still print the header? if self.rowcount == 0 and (not options["print_empty"] or not options["border"]): return "" # Get the rows we need to print, taking into account slicing, sorting, etc. rows = self._get_rows(options) # Turn all data in all rows into Unicode, formatted as desired formatted_rows = self._format_rows(rows, options) # Compute column widths self._compute_widths(formatted_rows, options) self._hrule = self._stringify_hrule(options) # Add title title = options["title"] or self._title if title: lines.append(self._stringify_title(title, options)) # Add header or top of border if options["header"]: lines.append(self._stringify_header(options)) elif options["border"] and options["hrules"] in (ALL, FRAME): lines.append(self._hrule) # Add rows for row in formatted_rows: lines.append(self._stringify_row(row, options)) # Add bottom of border if options["border"] and options["hrules"] == FRAME: lines.append(self._hrule) return self._unicode("\n").join(lines) def _stringify_hrule(self, options): if not options["border"]: return "" lpad, rpad = self._get_padding_widths(options) if options["vrules"] in (ALL, FRAME): bits = [options["junction_char"]] else: bits = [options["horizontal_char"]] # For tables with no data or fieldnames if not self._field_names: bits.append(options["junction_char"]) return "".join(bits) for field, width in zip(self._field_names, self._widths): if options["fields"] and field not in options["fields"]: continue bits.append((width + lpad + rpad) * options["horizontal_char"]) if options["vrules"] == ALL: bits.append(options["junction_char"]) else: bits.append(options["horizontal_char"]) if options["vrules"] == FRAME: bits.pop() bits.append(options["junction_char"]) return "".join(bits) def _stringify_title(self, title, options): lines = [] lpad, rpad = self._get_padding_widths(options) if options["border"]: if options["vrules"] == ALL: options["vrules"] = FRAME lines.append(self._stringify_hrule(options)) options["vrules"] = ALL elif options["vrules"] == FRAME: lines.append(self._stringify_hrule(options)) bits = [] endpoint = ( options["vertical_char"] if options["vrules"] in (ALL, FRAME) else " " ) bits.append(endpoint) title = " " * lpad + title + " " * rpad bits.append(self._justify(title, len(self._hrule) - 2, "c")) bits.append(endpoint) lines.append("".join(bits)) return "\n".join(lines) def _stringify_header(self, options): bits = [] lpad, rpad = self._get_padding_widths(options) if options["border"]: if options["hrules"] in (ALL, FRAME): bits.append(self._hrule) bits.append("\n") if options["vrules"] in (ALL, FRAME): bits.append(options["vertical_char"]) else: bits.append(" ") # For tables with no data or field names if not self._field_names: if options["vrules"] in (ALL, FRAME): bits.append(options["vertical_char"]) else: bits.append(" ") for (field, width) in zip(self._field_names, self._widths): if options["fields"] and field not in options["fields"]: continue if self._header_style == "cap": fieldname = field.capitalize() elif self._header_style == "title": fieldname = field.title() elif self._header_style == "upper": fieldname = field.upper() elif self._header_style == "lower": fieldname = field.lower() else: fieldname = field bits.append( " " * lpad + self._justify(fieldname, width, self._align[field]) + " " * rpad ) if options["border"]: if options["vrules"] == ALL: bits.append(options["vertical_char"]) else: bits.append(" ") # If vrules is FRAME, then we just appended a space at the end # of the last field, when we really want a vertical character if options["border"] and options["vrules"] == FRAME: bits.pop() bits.append(options["vertical_char"]) if options["border"] and options["hrules"] != NONE: bits.append("\n") bits.append(self._hrule) return "".join(bits) def _stringify_row(self, row, options): for (index, field, value, width) in zip( range(0, len(row)), self._field_names, row, self._widths ): # Enforce max widths lines = value.split("\n") new_lines = [] for line in lines: if _str_block_width(line) > width: line = textwrap.fill(line, width) new_lines.append(line) lines = new_lines value = "\n".join(lines) row[index] = value row_height = 0 for c in row: h = _get_size(c)[1] if h > row_height: row_height = h bits = [] lpad, rpad = self._get_padding_widths(options) for y in range(0, row_height): bits.append([]) if options["border"]: if options["vrules"] in (ALL, FRAME): bits[y].append(self.vertical_char) else: bits[y].append(" ") for (field, value, width) in zip(self._field_names, row, self._widths): valign = self._valign[field] lines = value.split("\n") dHeight = row_height - len(lines) if dHeight: if valign == "m": lines = ( [""] * int(dHeight / 2) + lines + [""] * (dHeight - int(dHeight / 2)) ) elif valign == "b": lines = [""] * dHeight + lines else: lines = lines + [""] * dHeight y = 0 for l in lines: if options["fields"] and field not in options["fields"]: continue bits[y].append( " " * lpad + self._justify(l, width, self._align[field]) + " " * rpad ) if options["border"]: if options["vrules"] == ALL: bits[y].append(self.vertical_char) else: bits[y].append(" ") y += 1 # If vrules is FRAME, then we just appended a space at the end # of the last field, when we really want a vertical character for y in range(0, row_height): if options["border"] and options["vrules"] == FRAME: bits[y].pop() bits[y].append(options["vertical_char"]) if options["border"] and options["hrules"] == ALL: bits[row_height - 1].append("\n") bits[row_height - 1].append(self._hrule) for y in range(0, row_height): bits[y] = "".join(bits[y]) return "\n".join(bits) def paginate(self, page_length=58, **kwargs): pages = [] kwargs["start"] = kwargs.get("start", 0) true_end = kwargs.get("end", self.rowcount) while True: kwargs["end"] = min(kwargs["start"] + page_length, true_end) pages.append(self.get_string(**kwargs)) if kwargs["end"] == true_end: break kwargs["start"] += page_length return "\f".join(pages) ############################## # JSON STRING METHODS # ############################## def get_json_string(self, **kwargs): """Return string representation of JSON formatted table in the current state Arguments: none yet""" options = self._get_options(kwargs) objects = [self.field_names] for row in self._get_rows(options): objects.append(dict(zip(self._field_names, row))) return json.dumps(objects, indent=4, separators=(",", ": "), sort_keys=True) ############################## # HTML STRING METHODS # ############################## def get_html_string(self, **kwargs): """Return string representation of HTML formatted version of table in current state. Arguments: title - optional table title start - index of first data row to include in output end - index of last data row to include in output PLUS ONE (list slice style) fields - names of fields (columns) to include header - print a header showing field names (True or False) border - print a border around the table (True or False) hrules - controls printing of horizontal rules after rows. Allowed values: ALL, FRAME, HEADER, NONE vrules - controls printing of vertical rules between columns. Allowed values: FRAME, ALL, NONE int_format - controls formatting of integer data float_format - controls formatting of floating point data padding_width - number of spaces on either side of column data (only used if left and right paddings are None) left_padding_width - number of spaces on left hand side of column data right_padding_width - number of spaces on right hand side of column data sortby - name of field to sort rows by sort_key - sorting key function, applied to data points before sorting attributes - dictionary of name/value pairs to include as HTML attributes in the
tag xhtml - print
tags if True,
tags if false""" options = self._get_options(kwargs) if options["format"]: string = self._get_formatted_html_string(options) else: string = self._get_simple_html_string(options) return string def _get_simple_html_string(self, options): lines = [] if options["xhtml"]: linebreak = "
" else: linebreak = "
" open_tag = ["") lines.append("".join(open_tag)) # Title title = options["title"] or self._title if title: cols = ( len(options["fields"]) if options["fields"] else len(self.field_names) ) lines.append(" ") lines.append(" " % (cols, title)) lines.append(" ") # Headers if options["header"]: lines.append(" ") for field in self._field_names: if options["fields"] and field not in options["fields"]: continue lines.append( " " % escape(field).replace("\n", linebreak) ) lines.append(" ") # Data rows = self._get_rows(options) formatted_rows = self._format_rows(rows, options) for row in formatted_rows: lines.append(" ") for field, datum in zip(self._field_names, row): if options["fields"] and field not in options["fields"]: continue lines.append( " " % escape(datum).replace("\n", linebreak) ) lines.append(" ") lines.append("
%s
%s
%s
") return self._unicode("\n").join(lines) def _get_formatted_html_string(self, options): lines = [] lpad, rpad = self._get_padding_widths(options) if options["xhtml"]: linebreak = "
" else: linebreak = "
" open_tag = ["") lines.append("".join(open_tag)) # Title title = options["title"] or self._title if title: cols = ( len(options["fields"]) if options["fields"] else len(self.field_names) ) lines.append(" ") lines.append(" %s" % (cols, title)) lines.append(" ") # Headers if options["header"]: lines.append(" ") for field in self._field_names: if options["fields"] and field not in options["fields"]: continue lines.append( ' %s' # noqa: E501 % (lpad, rpad, escape(field).replace("\n", linebreak)) ) lines.append(" ") # Data rows = self._get_rows(options) formatted_rows = self._format_rows(rows, options) aligns = [] valigns = [] for field in self._field_names: aligns.append( {"l": "left", "r": "right", "c": "center"}[self._align[field]] ) valigns.append( {"t": "top", "m": "middle", "b": "bottom"}[self._valign[field]] ) for row in formatted_rows: lines.append(" ") for field, datum, align, valign in zip( self._field_names, row, aligns, valigns ): if options["fields"] and field not in options["fields"]: continue lines.append( ' %s' # noqa: E501 % ( lpad, rpad, align, valign, escape(datum).replace("\n", linebreak), ) ) lines.append(" ") lines.append("") return self._unicode("\n").join(lines) ############################## # UNICODE WIDTH FUNCTIONS # ############################## def _char_block_width(char): # Basic Latin, which is probably the most common case # if char in xrange(0x0021, 0x007e): # if char >= 0x0021 and char <= 0x007e: if 0x0021 <= char <= 0x007E: return 1 # Chinese, Japanese, Korean (common) if 0x4E00 <= char <= 0x9FFF: return 2 # Hangul if 0xAC00 <= char <= 0xD7AF: return 2 # Combining? if unicodedata.combining(uni_chr(char)): return 0 # Hiragana and Katakana if 0x3040 <= char <= 0x309F or 0x30A0 <= char <= 0x30FF: return 2 # Full-width Latin characters if 0xFF01 <= char <= 0xFF60: return 2 # CJK punctuation if 0x3000 <= char <= 0x303E: return 2 # Backspace and delete if char in (0x0008, 0x007F): return -1 # Other control characters elif char in (0x0000, 0x000F, 0x001F): return 0 # Take a guess return 1 def _str_block_width(val): return sum(itermap(_char_block_width, itermap(ord, _re.sub("", val)))) ############################## # TABLE FACTORIES # ############################## def from_csv(fp, field_names=None, **kwargs): fmtparams = {} for param in [ "delimiter", "doublequote", "escapechar", "lineterminator", "quotechar", "quoting", "skipinitialspace", "strict", ]: if param in kwargs: fmtparams[param] = kwargs.pop(param) if fmtparams: reader = csv.reader(fp, **fmtparams) else: dialect = csv.Sniffer().sniff(fp.read(1024)) fp.seek(0) reader = csv.reader(fp, dialect) table = PrettyTable(**kwargs) if field_names: table.field_names = field_names else: if py3k: table.field_names = [x.strip() for x in next(reader)] else: table.field_names = [x.strip() for x in reader.next()] for row in reader: table.add_row([x.strip() for x in row]) return table def from_db_cursor(cursor, **kwargs): if cursor.description: table = PrettyTable(**kwargs) table.field_names = [col[0] for col in cursor.description] for row in cursor.fetchall(): table.add_row(row) return table def from_json(json_string, **kwargs): table = PrettyTable(**kwargs) objects = json.loads(json_string) table.field_names = objects[0] for obj in objects[1:]: row = [obj[key] for key in table.field_names] table.add_row(row) return table class TableHandler(HTMLParser): def __init__(self, **kwargs): HTMLParser.__init__(self) self.kwargs = kwargs self.tables = [] self.last_row = [] self.rows = [] self.max_row_width = 0 self.active = None self.last_content = "" self.is_last_row_header = False self.colspan = 0 def handle_starttag(self, tag, attrs): self.active = tag if tag == "th": self.is_last_row_header = True for (key, value) in attrs: if key == "colspan": self.colspan = int(value) def handle_endtag(self, tag): if tag in ["th", "td"]: stripped_content = self.last_content.strip() self.last_row.append(stripped_content) if self.colspan: for i in range(1, self.colspan): self.last_row.append("") self.colspan = 0 if tag == "tr": self.rows.append((self.last_row, self.is_last_row_header)) self.max_row_width = max(self.max_row_width, len(self.last_row)) self.last_row = [] self.is_last_row_header = False if tag == "table": table = self.generate_table(self.rows) self.tables.append(table) self.rows = [] self.last_content = " " self.active = None def handle_data(self, data): self.last_content += data def generate_table(self, rows): """ Generates from a list of rows a PrettyTable object. """ table = PrettyTable(**self.kwargs) for row in self.rows: if len(row[0]) < self.max_row_width: appends = self.max_row_width - len(row[0]) for i in range(1, appends): row[0].append("-") if row[1]: self.make_fields_unique(row[0]) table.field_names = row[0] else: table.add_row(row[0]) return table def make_fields_unique(self, fields): """ iterates over the row and make each field unique """ for i in range(0, len(fields)): for j in range(i + 1, len(fields)): if fields[i] == fields[j]: fields[j] += "'" def from_html(html_code, **kwargs): """ Generates a list of PrettyTables from a string of HTML code. Each in the HTML becomes one PrettyTable object. """ parser = TableHandler(**kwargs) parser.feed(html_code) return parser.tables def from_html_one(html_code, **kwargs): """ Generates a PrettyTables from a string of HTML code which contains only a single
""" tables = from_html(html_code, **kwargs) try: assert len(tables) == 1 except AssertionError: raise Exception( "More than one
in provided HTML code! Use from_html instead." ) return tables[0] ############################## # MAIN (TEST FUNCTION) # ############################## def main(): print("Generated using setters:") x = PrettyTable(["City name", "Area", "Population", "Annual Rainfall"]) x.title = "Australian capital cities" x.sortby = "Population" x.reversesort = True x.int_format["Area"] = "04" x.float_format = "6.1" x.align["City name"] = "l" # Left align city names x.add_row(["Adelaide", 1295, 1158259, 600.5]) x.add_row(["Brisbane", 5905, 1857594, 1146.4]) x.add_row(["Darwin", 112, 120900, 1714.7]) x.add_row(["Hobart", 1357, 205556, 619.5]) x.add_row(["Sydney", 2058, 4336374, 1214.8]) x.add_row(["Melbourne", 1566, 3806092, 646.9]) x.add_row(["Perth", 5386, 1554769, 869.4]) print(x) print print("Generated using constructor arguments:") y = PrettyTable( ["City name", "Area", "Population", "Annual Rainfall"], title="Australian capital cities", sortby="Population", reversesort=True, int_format="04", float_format="6.1", max_width=12, min_width=4, align="c", valign="t", ) y.align["City name"] = "l" # Left align city names y.add_row(["Adelaide", 1295, 1158259, 600.5]) y.add_row(["Brisbane", 5905, 1857594, 1146.4]) y.add_row(["Darwin", 112, 120900, 1714.7]) y.add_row(["Hobart", 1357, 205556, 619.5]) y.add_row(["Sydney", 2058, 4336374, 1214.8]) y.add_row(["Melbourne", 1566, 3806092, 646.9]) y.add_row(["Perth", 5386, 1554769, 869.4]) print(y) if __name__ == "__main__": main() pyvisa-1.11.3/pyvisa/typing.py000066400000000000000000000026371375165327600163360ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Type aliases allowing to narrow down definition and reduce duplication This file is part of PyVISA. :copyright: 2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ from typing import Any, Callable, NewType from . import constants #: Type alias used to identify VISA resource manager sessions VISARMSession = NewType("VISARMSession", int) #: Type alias used to identify VISA resource sessions VISASession = NewType("VISASession", int) #: Type alias used to identify an event context (created when handling an event) VISAEventContext = NewType("VISAEventContext", int) #: Type alias used to identify a job id created during an asynchronous operation #: JobID should always be treated as opaque objects since their exact behavior #: may depend on the backend in use. VISAJobID = NewType("VISAJobID", object) #: Type alias used to identify a memory address in a register based resource after #: it has been mapped VISAMemoryAddress = NewType("VISAMemoryAddress", int) #: Type for event handler passed to the VISA library. The last argument is the #: user handle specified when registering the handler. The value that will be #: passed to the handler is the value as interpreted by the backend and returned #: by the install_visa_handler method of the library object. VISAHandler = Callable[[VISASession, constants.EventType, VISAEventContext, Any], None] pyvisa-1.11.3/pyvisa/util.py000066400000000000000000000736621375165327600160070ustar00rootroot00000000000000# -*- coding: utf-8 -*- """General utility functions. This file is part of PyVISA. :copyright: 2014-2020 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see LICENSE for more details. """ import functools import inspect import io import math import os import platform import struct import subprocess import sys import warnings from collections import OrderedDict from typing import ( Any, Callable, Dict, Iterable, List, Optional, Sequence, Tuple, Type, Union, overload, ) from typing_extensions import Literal from . import constants, logger try: import numpy as np # type: ignore except ImportError: np = None #: Length of the header found before a binary block (ieee or hp) that will #: trigger a warning to alert the user of a possibly incorrect answer from the #: instrument. In general binary block are not prefixed by a header and finding #: a long one may mean that we picked up a # in the bulk of the message. DEFAULT_LENGTH_BEFORE_BLOCK = 25 def _use_numpy_routines(container: Union[type, Callable]) -> bool: """Should optimized numpy routines be used to extract data.""" if np is None or container in (tuple, list): return False if container is np.array or ( inspect.isclass(container) and issubclass(container, np.ndarray) # type: ignore ): return True return False def read_user_library_path() -> Optional[str]: """Return the library path stored in one of the following configuration files: /share/pyvisa/.pyvisarc ~/.pyvisarc is the site-specific directory prefix where the platform independent Python files are installed. Example configuration file: [Paths] visa library=/my/path/visa.so dll_extra_paths=/my/otherpath/;/my/otherpath2 Return `None` if configuration files or keys are not present. """ from configparser import ConfigParser, NoOptionError, NoSectionError config_parser = ConfigParser() files = config_parser.read( [ os.path.join(sys.prefix, "share", "pyvisa", ".pyvisarc"), os.path.join(os.path.expanduser("~"), ".pyvisarc"), ] ) if not files: logger.debug("No user defined library files") return None logger.debug("User defined library files: %s" % files) try: return config_parser.get("Paths", "visa library") except (NoOptionError, NoSectionError): logger.debug("NoOptionError or NoSectionError while reading config file") return None def add_user_dll_extra_paths() -> Optional[List[str]]: """Add paths to search for .dll dependencies on Windows. The configuration files are expected to be stored in one of the following location: /share/pyvisa/.pyvisarc ~/.pyvisarc is the site-specific directory prefix where the platform independent Python files are installed. Example configuration file: [Paths] visa library=/my/path/visa.so dll_extra_paths=/my/otherpath/;/my/otherpath2 """ from configparser import ConfigParser, NoOptionError, NoSectionError # os.add_dll_library_path has been added in Python 3.8 if sys.version_info >= (3, 8) and sys.platform == "win32": config_parser = ConfigParser() files = config_parser.read( [ os.path.join(sys.prefix, "share", "pyvisa", ".pyvisarc"), os.path.join(os.path.expanduser("~"), ".pyvisarc"), ] ) if not files: logger.debug("No user defined configuration") return None logger.debug("User defined configuration files: %s" % files) try: dll_extra_paths = config_parser.get("Paths", "dll_extra_paths").split(";") for path in dll_extra_paths: os.add_dll_directory(path) return dll_extra_paths except (NoOptionError, NoSectionError): logger.debug( "NoOptionError or NoSectionError while reading config file for" " dll_extra_paths." ) return None else: logger.debug( "Not loading dll_extra_paths because we are not on Windows " "or Python < 3.8" ) return None class LibraryPath(str): """Object encapsulating information about a VISA dynamic library.""" #: Path with which the object was created path: str #: Detection method employed to locate the library found_by: str #: Architectural information (32, ) or (64, ) or (32, 64) _arch: Optional[Tuple[int, ...]] = None def __new__( cls: Type["LibraryPath"], path: str, found_by: str = "auto" ) -> "LibraryPath": obj = super(LibraryPath, cls).__new__(cls, path) # type: ignore obj.path = path obj.found_by = found_by return obj @property def arch(self) -> Tuple[int, ...]: """Architecture of the library.""" if self._arch is None: try: self._arch = get_arch(self.path) except Exception: self._arch = tuple() return self._arch @property def is_32bit(self) -> Union[bool, Literal["n/a"]]: """Is the library 32 bits.""" if not self.arch: return "n/a" return 32 in self.arch @property def is_64bit(self) -> Union[bool, Literal["n/a"]]: """Is the library 64 bits.""" if not self.arch: return "n/a" return 64 in self.arch @property def bitness(self) -> str: """Bitness of the library.""" if not self.arch: return "n/a" return ", ".join(str(a) for a in self.arch) def cleanup_timeout(timeout: Optional[Union[int, float]]) -> int: """Turn a timeout expressed as a float into in interger or the proper constant.""" if timeout is None or math.isinf(timeout): timeout = constants.VI_TMO_INFINITE elif timeout < 1: timeout = constants.VI_TMO_IMMEDIATE elif not (1 <= timeout <= 4294967294): raise ValueError("timeout value is invalid") else: timeout = int(timeout) return timeout def warn_for_invalid_kwargs(keyw, allowed_keys): # pragma: no cover warnings.warn("warn_for_invalid_kwargs will be removed in 1.12", FutureWarning) for key in keyw.keys(): if key not in allowed_keys: warnings.warn('Keyword argument "%s" unknown' % key, stacklevel=3) def filter_kwargs(keyw, selected_keys): # pragma: no cover warnings.warn("warn_for_invalid_kwargs will be removed in 1.12", FutureWarning) result = {} for key, value in keyw.items(): if key in selected_keys: result[key] = value return result def split_kwargs(keyw, self_keys, parent_keys, warn=True): # pragma: no cover warnings.warn("warn_for_invalid_kwargs will be removed in 1.12", FutureWarning) self_kwargs = dict() parent_kwargs = dict() self_keys = set(self_keys) parent_keys = set(parent_keys) all_keys = self_keys | parent_keys for key, value in keyw.items(): if warn and key not in all_keys: warnings.warn('Keyword argument "%s" unknown' % key, stacklevel=3) if key in self_keys: self_kwargs[key] = value if key in parent_keys: parent_kwargs[key] = value return self_kwargs, parent_kwargs _converters: Dict[str, Callable[[str], Any]] = { "s": str, "b": functools.partial(int, base=2), "c": ord, "d": int, "o": functools.partial(int, base=8), "x": functools.partial(int, base=16), "X": functools.partial(int, base=16), "h": functools.partial(int, base=16), "H": functools.partial(int, base=16), "e": float, "E": float, "f": float, "F": float, "g": float, "G": float, } _np_converters = { "d": "i", "e": "d", "E": "d", "f": "d", "F": "d", "g": "d", "G": "d", } ASCII_CONVERTER = Union[ Literal["s", "b", "c", "d", "o", "x", "X", "e", "E", "f", "F", "g", "G"], Callable[[str], Any], ] def from_ascii_block( ascii_data: str, converter: ASCII_CONVERTER = "f", separator: Union[str, Callable[[str], Iterable[str]]] = ",", container: Callable[ [Iterable[Union[int, float]]], Sequence[Union[int, float]] ] = list, ) -> Sequence: """Parse ascii data and return an iterable of numbers. Parameters ---------- ascii_data : str Data to be parsed. converter : ASCII_CONVERTER, optional Str format of function to convert each value. Default to "f". separator : Union[str, Callable[[str], Iterable[str]]] str or callable used to split the data into individual elements. If a str is given, data.split(separator) is used. Default to ",". container : Union[Type, Callable[[Iterable], Sequence]], optional Container type to use for the output data. Possible values are: list, tuple, np.ndarray, etc, Default to list. Returns ------- Sequence Parsed data. """ if ( _use_numpy_routines(container) and isinstance(converter, str) and isinstance(separator, str) and converter in _np_converters ): return np.fromstring(ascii_data, _np_converters[converter], sep=separator) if isinstance(converter, str): try: converter = _converters[converter] except KeyError: raise ValueError( "Invalid code for converter: %s not in %s" % (converter, str(tuple(_converters.keys()))) ) data: Iterable[str] if isinstance(separator, str): data = ascii_data.split(separator) else: data = separator(ascii_data) return container([converter(raw_value) for raw_value in data]) def to_ascii_block( iterable: Iterable[Any], converter: Union[str, Callable[[Any], str]] = "f", separator: Union[str, Callable[[Iterable[str]], str]] = ",", ) -> str: """Turn an iterable of numbers in an ascii block of data. Parameters ---------- iterable : Iterable[Any] Data to be formatted. converter : Union[str, Callable[[Any], str]] String formatting code or function used to convert each value. Default to "f". separator : Union[str, Callable[[Iterable[str]], str]] str or callable that join individual elements into a str. If a str is given, separator.join(data) is used. """ if isinstance(separator, str): separator = separator.join if isinstance(converter, str): converter = "%" + converter block = separator(converter % val for val in iterable) else: block = separator(converter(val) for val in iterable) return block #: Valid binary header when reading/writing binary block of data from an instrument BINARY_HEADERS = Literal["ieee", "hp", "empty"] #: Valid datatype for binary block. See Python standard library struct module for more #: details. BINARY_DATATYPES = Literal[ "s", "b", "B", "h", "H", "i", "I", "l", "L", "q", "Q", "f", "d" ] #: Valid output containers for storing the parsed binary data BINARY_CONTAINERS = Union[type, Callable] def parse_ieee_block_header( block: Union[bytes, bytearray], length_before_block: Optional[int] = None, raise_on_late_block: bool = False, ) -> Tuple[int, int]: """Parse the header of a IEEE block. Definite Length Arbitrary Block: # The header_length specifies the size of the data_length field. And the data_length field specifies the size of the data. Indefinite Length Arbitrary Block: #0 In this case the data length returned will be 0. The actual length can be deduced from the block and the offset. Parameters ---------- block : Union[bytes, bytearray] IEEE formatted block of data. length_before_block : Optional[int], optional Number of bytes before the actual start of the block. Default to None, which means that number will be inferred. raise_on_late_block : bool, optional Raise an error in the beginning of the block is not found before DEFAULT_LENGTH_BEFORE_BLOCK, if False use a warning. Default to False. Returns ------- int Offset at which the actual data starts int Length of the data in bytes. """ begin = block.find(b"#") if begin < 0: raise ValueError( "Could not find hash sign (#) indicating the start of the block. " "The block begin by %r" % block[:25] ) length_before_block = length_before_block or DEFAULT_LENGTH_BEFORE_BLOCK if begin > length_before_block: msg = ( "The beginning of the block has been found at %d which " "is an unexpectedly large value. The actual block may " "have been missing a beginning marker but the block " "contained one:\n%s" ) % (begin, repr(block)) if raise_on_late_block: raise RuntimeError(msg) else: warnings.warn(msg, UserWarning) try: # int(block[begin+1]) != int(block[begin+1:begin+2]) in Python 3 header_length = int(block[begin + 1 : begin + 2]) except ValueError: header_length = 0 offset = begin + 2 + header_length if header_length > 0: # #3100DATA # 012345 data_length = int(block[begin + 2 : offset]) else: # #0DATA # 012 data_length = 0 return offset, data_length def parse_hp_block_header( block: Union[bytes, bytearray], is_big_endian: bool, length_before_block: int = None, raise_on_late_block: bool = False, ) -> Tuple[int, int]: """Parse the header of a HP block. Definite Length Arbitrary Block: #A The header ia always 4 bytes long. The data_length field specifies the size of the data. Parameters ---------- block : Union[bytes, bytearray] HP formatted block of data. is_big_endian : bool Is the header in big or little endian order. length_before_block : Optional[int], optional Number of bytes before the actual start of the block. Default to None, which means that number will be inferred. raise_on_late_block : bool, optional Raise an error in the beginning of the block is not found before DEFAULT_LENGTH_BEFORE_BLOCK, if False use a warning. Default to False. Returns ------- int Offset at which the actual data starts int Length of the data in bytes. """ begin = block.find(b"#A") if begin < 0: raise ValueError( "Could not find the standard block header (#A) indicating the start " "of the block. The block begin by %r" % block[:25] ) length_before_block = length_before_block or DEFAULT_LENGTH_BEFORE_BLOCK if begin > length_before_block: msg = ( "The beginning of the block has been found at %d which " "is an unexpectedly large value. The actual block may " "have been missing a beginning marker but the block " "contained one:\n%s" ) % (begin, repr(block)) if raise_on_late_block: raise RuntimeError(msg) else: warnings.warn(msg, UserWarning) offset = begin + 4 data_length = int.from_bytes( block[begin + 2 : offset], byteorder="big" if is_big_endian else "little" ) return offset, data_length def from_ieee_block( block: Union[bytes, bytearray], datatype: BINARY_DATATYPES = "f", is_big_endian: bool = False, container: Callable[ [Iterable[Union[int, float]]], Sequence[Union[int, float]] ] = list, ) -> Sequence[Union[int, float]]: """Convert a block in the IEEE format into an iterable of numbers. Definite Length Arbitrary Block: # The header_length specifies the size of the data_length field. And the data_length field specifies the size of the data. Indefinite Length Arbitrary Block: #0 Parameters ---------- block : Union[bytes, bytearray] IEEE formatted block of data. datatype : BINARY_DATATYPES, optional Format string for a single element. See struct module. 'f' by default. is_big_endian : bool, optional Are the data in big or little endian order. container : Union[Type, Callable[[Iterable], Sequence]], optional Container type to use for the output data. Possible values are: list, tuple, np.ndarray, etc, Default to list. Returns ------- Sequence[Union[int, float]] Parsed data. """ offset, data_length = parse_ieee_block_header(block) # If the data length is not reported takes all the data and do not make # any assumption about the termination character if data_length == 0: data_length = len(block) - offset if len(block) < offset + data_length: raise ValueError( "Binary data is incomplete. The header states %d data" " bytes, but %d where received." % (data_length, len(block) - offset) ) return from_binary_block( block, offset, data_length, datatype, is_big_endian, container ) def from_hp_block( block: Union[bytes, bytearray], datatype: BINARY_DATATYPES = "f", is_big_endian: bool = False, container: Callable[ [Iterable[Union[int, float]]], Sequence[Union[int, float]] ] = list, ) -> Sequence[Union[int, float]]: """Convert a block in the HP format into an iterable of numbers. Definite Length Arbitrary Block: #A The header ia always 4 bytes long. The data_length field specifies the size of the data. Parameters ---------- block : Union[bytes, bytearray] HP formatted block of data. datatype : BINARY_DATATYPES, optional Format string for a single element. See struct module. 'f' by default. is_big_endian : bool, optional Are the data in big or little endian order. container : Union[Type, Callable[[Iterable], Sequence]], optional Container type to use for the output data. Possible values are: list, tuple, np.ndarray, etc, Default to list. Returns ------- Sequence[Union[int, float]] Parsed data. """ offset, data_length = parse_hp_block_header(block, is_big_endian) # If the data length is not reported takes all the data and do not make # any assumption about the termination character if data_length == 0: data_length = len(block) - offset if len(block) < offset + data_length: raise ValueError( "Binary data is incomplete. The header states %d data" " bytes, but %d where received." % (data_length, len(block) - offset) ) return from_binary_block( block, offset, data_length, datatype, is_big_endian, container ) def from_binary_block( block: Union[bytes, bytearray], offset: int = 0, data_length: Optional[int] = None, datatype: BINARY_DATATYPES = "f", is_big_endian: bool = False, container: Callable[ [Iterable[Union[int, float]]], Sequence[Union[int, float]] ] = list, ) -> Sequence[Union[int, float]]: """Convert a binary block into an iterable of numbers. Parameters ---------- block : Union[bytes, bytearray] HP formatted block of data. offset : int Offset at which the actual data starts data_length : int Length of the data in bytes. datatype : BINARY_DATATYPES, optional Format string for a single element. See struct module. 'f' by default. is_big_endian : bool, optional Are the data in big or little endian order. container : Union[Type, Callable[[Iterable], Sequence]], optional Container type to use for the output data. Possible values are: list, tuple, np.ndarray, etc, Default to list. Returns ------- Sequence[Union[int, float]] Parsed data. """ if data_length is None: data_length = len(block) - offset element_length = struct.calcsize(datatype) array_length = int(data_length / element_length) endianess = ">" if is_big_endian else "<" if _use_numpy_routines(container): return np.frombuffer(block, endianess + datatype, array_length, offset) fullfmt = "%s%d%s" % (endianess, array_length, datatype) try: raw_data = struct.unpack_from(fullfmt, block, offset) except struct.error: raise ValueError("Binary data was malformed") if datatype in "sp": raw_data = raw_data[0] return container(raw_data) def to_binary_block( iterable: Sequence[Union[int, float]], header: Union[str, bytes], datatype: BINARY_DATATYPES, is_big_endian: bool, ) -> bytes: """Convert an iterable of numbers into a block of data with a given header. Parameters ---------- iterable : Sequence[Union[int, float]] Sequence of numbers to pack into a block. header : Union[str, bytes] Header which should prefix the binary block datatype : BINARY_DATATYPES Format string for a single element. See struct module. is_big_endian : bool Are the data in big or little endian order. Returns ------- bytes Binary block of data preceded by the specified header """ array_length = len(iterable) endianess = ">" if is_big_endian else "<" fullfmt = "%s%d%s" % (endianess, array_length, datatype) if isinstance(header, str): header = bytes(header, "ascii") if datatype in ("s", "p"): block = struct.pack(fullfmt, iterable) else: block = struct.pack(fullfmt, *iterable) return header + block def to_ieee_block( iterable: Sequence[Union[int, float]], datatype: BINARY_DATATYPES = "f", is_big_endian: bool = False, ) -> bytes: """Convert an iterable of numbers into a block of data in the IEEE format. Parameters ---------- iterable : Sequence[Union[int, float]] Sequence of numbers to pack into a block. datatype : BINARY_DATATYPES, optional Format string for a single element. See struct module. Default to 'f'. is_big_endian : bool, optional Are the data in big or little endian order. Default to False. Returns ------- bytes Binary block of data preceded by the specified header """ array_length = len(iterable) element_length = struct.calcsize(datatype) data_length = array_length * element_length header = "%d" % data_length header = "#%d%s" % (len(header), header) return to_binary_block(iterable, header, datatype, is_big_endian) def to_hp_block( iterable: Sequence[Union[int, float]], datatype: BINARY_DATATYPES = "f", is_big_endian: bool = False, ) -> bytes: """Convert an iterable of numbers into a block of data in the HP format. Parameters ---------- iterable : Sequence[Union[int, float]] Sequence of numbers to pack into a block. datatype : BINARY_DATATYPES, optional Format string for a single element. See struct module. Default to 'f'. is_big_endian : bool, optional Are the data in big or little endian order. Default to False. Returns ------- bytes Binary block of data preceded by the specified header """ array_length = len(iterable) element_length = struct.calcsize(datatype) data_length = array_length * element_length header = b"#A" + ( int.to_bytes(data_length, 2, "big" if is_big_endian else "little") ) return to_binary_block(iterable, header, datatype, is_big_endian) def get_system_details(backends: bool = True) -> Dict[str, str]: """Return a dictionary with information about the system.""" buildno, builddate = platform.python_build() if sys.maxunicode == 65535: # UCS2 build (standard) unitype = "UCS2" else: # UCS4 build (most recent Linux distros) unitype = "UCS4" bits, linkage = platform.architecture() from . import __version__ d = { "platform": platform.platform(), "processor": platform.processor(), "executable": sys.executable, "implementation": getattr(platform, "python_implementation", lambda: "n/a")(), "python": platform.python_version(), "compiler": platform.python_compiler(), "buildno": buildno, "builddate": builddate, "unicode": unitype, "bits": bits, "pyvisa": __version__, "backends": OrderedDict(), } if backends: from . import highlevel for backend in highlevel.list_backends(): if backend.startswith("pyvisa-"): backend = backend[7:] try: cls = highlevel.get_wrapper_class(backend) except Exception as e: d["backends"][backend] = [ "Could not instantiate backend", "-> %s" % str(e), ] continue try: d["backends"][backend] = cls.get_debug_info() except Exception as e: d["backends"][backend] = [ "Could not obtain debug info", "-> %s" % str(e), ] return d def system_details_to_str(d: Dict[str, str], indent: str = "") -> str: """Convert the system details to a str. System details can be obtained by `get_system_details`. """ details = [ "Machine Details:", " Platform ID: %s" % d.get("platform", "n/a"), " Processor: %s" % d.get("processor", "n/a"), "", "Python:", " Implementation: %s" % d.get("implementation", "n/a"), " Executable: %s" % d.get("executable", "n/a"), " Version: %s" % d.get("python", "n/a"), " Compiler: %s" % d.get("compiler", "n/a"), " Bits: %s" % d.get("bits", "n/a"), " Build: %s (#%s)" % (d.get("builddate", "n/a"), d.get("buildno", "n/a")), " Unicode: %s" % d.get("unicode", "n/a"), "", "PyVISA Version: %s" % d.get("pyvisa", "n/a"), "", ] def _to_list(key, value, indent_level=0): sp = " " * indent_level * 3 if isinstance(value, str): if key: return ["%s%s: %s" % (sp, key, value)] else: return ["%s%s" % (sp, value)] elif isinstance(value, dict): if key: al = ["%s%s:" % (sp, key)] else: al = [] for k, v in value.items(): al.extend(_to_list(k, v, indent_level + 1)) return al elif isinstance(value, (tuple, list)): if key: al = ["%s%s:" % (sp, key)] else: al = [] for v in value: al.extend(_to_list(None, v, indent_level + 1)) return al else: return ["%s" % value] details.extend(_to_list("Backends", d["backends"])) joiner = "\n" + indent return indent + joiner.join(details) + "\n" @overload def get_debug_info(to_screen: Literal[True] = True) -> None: pass @overload def get_debug_info(to_screen: Literal[False]) -> str: pass def get_debug_info(to_screen=True): """Get the PyVISA debug information.""" out = system_details_to_str(get_system_details()) if not to_screen: return out print(out) def pip_install(package): # pragma: no cover warnings.warn("warn_for_invalid_kwargs will be removed in 1.12", FutureWarning) try: import pip # type: ignore return pip.main(["install", package]) except ImportError: print(system_details_to_str(get_system_details())) raise RuntimeError("Please install pip to continue.") machine_types = { 0: "UNKNOWN", 0x014C: "I386", 0x0162: "R3000", 0x0166: "R4000", 0x0168: "R10000", 0x0169: "WCEMIPSV2", 0x0184: "ALPHA", 0x01A2: "SH3", 0x01A3: "SH3DSP", 0x01A4: "SH3E", 0x01A6: "SH4", 0x01A8: "SH5", 0x01C0: "ARM", 0x01C2: "THUMB", 0x01C4: "ARMNT", 0x01D3: "AM33", 0x01F0: "POWERPC", 0x01F1: "POWERPCFP", 0x0200: "IA64", 0x0266: "MIPS16", 0x0284: "ALPHA64", # 0x0284: 'AXP64', # same 0x0366: "MIPSFPU", 0x0466: "MIPSFPU16", 0x0520: "TRICORE", 0x0CEF: "CEF", 0x0EBC: "EBC", 0x8664: "AMD64", 0x9041: "M32R", 0xC0EE: "CEE", } def get_shared_library_arch(filename: str) -> str: """Get the architecture of shared library.""" with io.open(filename, "rb") as fp: dos_headers = fp.read(64) _ = fp.read(4) magic, skip, offset = struct.unpack("=2s58sl", dos_headers) if magic != b"MZ": raise Exception("Not an executable") fp.seek(offset, io.SEEK_SET) pe_header = fp.read(6) sig, skip, machine = struct.unpack(str("=2s2sH"), pe_header) if sig != b"PE": raise Exception("Not a PE executable") return machine_types.get(machine, "UNKNOWN") def get_arch(filename: str) -> Tuple[int, ...]: """Get the architecture of the platform.""" this_platform = sys.platform if this_platform.startswith("win"): machine_type = get_shared_library_arch(filename) if machine_type == "I386": return (32,) elif machine_type in ("IA64", "AMD64"): return (64,) else: return () elif this_platform not in ("linux2", "linux3", "linux", "darwin"): raise OSError("Unsupported platform: %s" % this_platform) res = subprocess.run(["file", filename], capture_output=True) out = res.stdout.decode("ascii") ret = [] if this_platform.startswith("linux"): if "32-bit" in out: ret.append(32) if "64-bit" in out: ret.append(64) else: # darwin if "(for architecture i386)" in out: ret.append(32) if "(for architecture x86_64)" in out: ret.append(64) return tuple(ret) pyvisa-1.11.3/setup.cfg000066400000000000000000000056241375165327600147570ustar00rootroot00000000000000[metadata] name = PyVISA author = Torsten Bronger, Gregor Thalhammer author_email = bronger@physik.rwth-aachen.de maintainer = Matthieu C. Dartiailh maintainer_email = m.dartiailh@gmail.com license = MIT License description = Python VISA bindings for GPIB, RS232, TCPIP and USB instruments keywords = VISA GPIB USB serial RS232 measurement acquisition url = https://github.com/pyvisa/pyvisa long_description = file: README.rst, AUTHORS, CHANGES long_description_content_type = text/x-rst classifiers = Development Status :: 5 - Production/Stable Intended Audience :: Developers Intended Audience :: Science/Research License :: OSI Approved :: MIT License Operating System :: Microsoft :: Windows Operating System :: POSIX :: Linux Operating System :: MacOS :: MacOS X Programming Language :: Python Topic :: Scientific/Engineering :: Interface Engine/Protocol Translator Topic :: Software Development :: Libraries :: Python Modules Programming Language :: Python :: 3 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 platforms = Linux,, Windows,, Mac [options] py_modules = visa packages = pyvisa pyvisa.ctwrapper pyvisa.resources pyvisa.thirdparty pyvisa.testsuite pyvisa.testsuite.fake-extensions pyvisa.testsuite.keysight_assisted_tests zip_safe = False setup_requires = setuptools_scm>=3.4.3 install_requires = typing_extensions importlib-metadata; python_version<"3.8" dataclasses; python_version<"3.7" python_requires = >=3.6 use_2to3 = False platforms = Linux; Windows; Mac test_suite = pyvisa.testsuite.testsuite setup_require = setuptools>=42; wheel; setuptools_scm[toml]>=3.4.3 [options.entry_points] console_scripts = pyvisa-shell=pyvisa.cmd_line_tools:visa_shell pyvisa-info=pyvisa.cmd_line_tools:visa_info [options.package_data] * = *.dll pyvisa = py.typed [flake8] exclude = .git, __pycache__, docs/source/conf.py, old, build, dist, pyvisa/thirdparty/*, visa.py, ignore = E203, E266, E501, W503, E731 # line length is intentionally set to 80 here because pyvisa uses Bugbear # See https://github.com/psf/black/blob/master/README.md#line-length for more details max-line-length = 80 max-complexity = 18 select = B,C,E,F,W,T4,B9 per-file-ignores = pyvisa/__init__.py:E402 pyvisa/constants.py:E221 [mypy] follow_imports = ignore strict_optional = True # XXX Ideally remove once pytest ships typing information [mypy-pytest.*] ignore_missing_imports = True [mypy-pyvisa.thirdparty.*] ignore_errors = True [isort] multi_line_output = 3 include_trailing_comma = true force_grid_wrap = 0 use_parentheses = true line_length = 88 skip = pyvisa/thirdparty/prettytable.py, pyvisa/__init__.py known_third_party = numpy,importlib_metadata,setuptools,typing_extensions, pytest pyvisa-1.11.3/setup.py000066400000000000000000000002101375165327600146320ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- from setuptools import setup if __name__ == "__main__": setup(use_scm_version=True) pyvisa-1.11.3/visa.py000066400000000000000000000027061375165327600144500ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Module to provide an import shortcut for the most common VISA operations. This file is part of PyVISA. :copyright: 2014-2019 by PyVISA Authors, see AUTHORS for more details. :license: MIT, see COPYING for more details. """ import warnings warnings.warn( ( "The visa module provided by PyVISA is being deprecated. " "You can replace `import visa` by `import pyvisa as visa` " "to achieve the same effect.\n\n" "The reason for the deprecation is the possible conflict with " "the visa package provided by the " "https://github.com/visa-sdk/visa-python which can result in " "hard to debug situations." ), FutureWarning, ) from pyvisa import logger, __version__, log_to_screen, constants from pyvisa.highlevel import ResourceManager from pyvisa.errors import ( Error, VisaIOError, VisaIOWarning, VisaTypeError, UnknownHandler, OSNotSupported, InvalidBinaryFormat, InvalidSession, LibraryError, ) # This is needed to registry all resources. from pyvisa.resources import Resource from pyvisa.cmd_line_tools import visa_main __all__ = [ "ResourceManager", "constants", "logger", "Error", "VisaIOError", "VisaIOWarning", "VisaTypeError", "UnknownHandler", "OSNotSupported", "InvalidBinaryFormat", "InvalidSession", "LibraryError", "log_to_screen", ] if __name__ == "__main__": visa_main()