From 96847dd15feda1d854623d03a79a0f7f848c4495 Mon Sep 17 00:00:00 2001 From: Ruben Undheim Date: Tue, 1 Sep 2015 22:26:12 +0200 Subject: Import pyvisa_1.8.orig.tar.gz [dgit import orig pyvisa_1.8.orig.tar.gz] --- .gitignore | 15 + .travis.yml | 20 + AUTHORS | 25 + CHANGES | 292 ++ ChangeLog | 995 +++++ LICENSE | 21 + MANIFEST.in | 7 + README | 69 + docs/LICENSE | 23 + docs/Makefile | 153 + docs/_static/logo-full.jpg | Bin 0 -> 10898 bytes docs/_templates/sidebarintro.html | 20 + docs/_templates/sidebarlogo.html | 23 + docs/_themes/.gitignore | 3 + docs/_themes/LICENSE | 37 + docs/_themes/README | 31 + docs/_themes/flask/layout.html | 30 + docs/_themes/flask/relations.html | 20 + docs/_themes/flask/static/flasky.css_t | 395 ++ docs/_themes/flask/static/small_flask.css | 70 + docs/_themes/flask/theme.conf | 10 + docs/_themes/flask_theme_support.py | 86 + docs/_themes/sphinx_rtd_theme/__init__.py | 17 + docs/_themes/sphinx_rtd_theme/breadcrumbs.html | 19 + docs/_themes/sphinx_rtd_theme/footer.html | 32 + docs/_themes/sphinx_rtd_theme/layout.html | 161 + docs/_themes/sphinx_rtd_theme/layout_old.html | 205 + docs/_themes/sphinx_rtd_theme/search.html | 50 + docs/_themes/sphinx_rtd_theme/searchbox.html | 7 + .../sphinx_rtd_theme/static/css/badge_only.css | 224 + docs/_themes/sphinx_rtd_theme/static/css/theme.css | 4725 ++++++++++++++++++++ .../sphinx_rtd_theme/static/fonts/FontAwesome.otf | Bin 0 -> 62856 bytes .../static/fonts/fontawesome-webfont.eot | Bin 0 -> 38205 bytes .../static/fonts/fontawesome-webfont.svg | 414 ++ .../static/fonts/fontawesome-webfont.ttf | Bin 0 -> 80652 bytes .../static/fonts/fontawesome-webfont.woff | Bin 0 -> 44432 bytes docs/_themes/sphinx_rtd_theme/static/js/theme.js | 47 + docs/_themes/sphinx_rtd_theme/theme.conf | 9 + docs/_themes/sphinx_rtd_theme/versions.html | 37 + docs/api/constants.rst | 45 + docs/api/index.rst | 14 + docs/api/resourcemanager.rst | 9 + docs/api/resources.rst | 135 + docs/api/visalibrarybase.rst | 9 + docs/architecture.rst | 105 + docs/backends.rst | 182 + docs/conf.py | 297 ++ docs/configuring.rst | 61 + docs/contributing.rst | 76 + docs/default.css | 255 ++ docs/example.rst | 72 + docs/faq.rst | 174 + docs/getting.rst | 62 + docs/getting_nivisa.rst | 68 + docs/index.rst | 85 + docs/make.bat | 190 + docs/migrating.rst | 294 ++ docs/names.rst | 157 + docs/resources.rst | 166 + docs/rvalues.rst | 181 + docs/shell.rst | 113 + docs/tutorial.rst | 91 + examples/itc4.py | 43 + examples/keithley2000.py | 51 + pyvisa/__init__.py | 51 + pyvisa/attributes.py | 3289 ++++++++++++++ pyvisa/compat/__init__.py | 71 + pyvisa/compat/check_output.py | 35 + pyvisa/compat/nullhandler.py | 35 + pyvisa/compat/ordereddict.py | 127 + pyvisa/compat/struct.py | 42 + pyvisa/constants.py | 1060 +++++ pyvisa/ctwrapper/__init__.py | 19 + pyvisa/ctwrapper/cthelper.py | 85 + pyvisa/ctwrapper/functions.py | 1899 ++++++++ pyvisa/ctwrapper/highlevel.py | 218 + pyvisa/ctwrapper/types.py | 157 + pyvisa/errors.py | 513 +++ pyvisa/highlevel.py | 1652 +++++++ pyvisa/resources/__init__.py | 39 + pyvisa/resources/firewire.py | 29 + pyvisa/resources/gpib.py | 148 + pyvisa/resources/messagebased.py | 545 +++ pyvisa/resources/pxi.py | 42 + pyvisa/resources/registerbased.py | 72 + pyvisa/resources/resource.py | 397 ++ pyvisa/resources/serial.py | 34 + pyvisa/resources/tcpip.py | 41 + pyvisa/resources/usb.py | 68 + pyvisa/resources/vxi.py | 52 + pyvisa/rname.py | 573 +++ pyvisa/shell.py | 327 ++ pyvisa/testsuite/__init__.py | 88 + pyvisa/testsuite/test_rname.py | 256 ++ pyvisa/testsuite/test_util.py | 60 + pyvisa/thirdparty/__init__.py | 12 + pyvisa/thirdparty/prettytable.py | 1475 ++++++ pyvisa/util.py | 593 +++ setup.cfg | 4 + setup.py | 76 + tox.ini | 11 + visa.py | 39 + 102 files changed, 25461 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 AUTHORS create mode 100644 CHANGES create mode 100644 ChangeLog create mode 100644 LICENSE create mode 100644 MANIFEST.in create mode 100644 README create mode 100644 docs/LICENSE create mode 100644 docs/Makefile create mode 100644 docs/_static/logo-full.jpg create mode 100644 docs/_templates/sidebarintro.html create mode 100644 docs/_templates/sidebarlogo.html create mode 100644 docs/_themes/.gitignore create mode 100644 docs/_themes/LICENSE create mode 100644 docs/_themes/README create mode 100644 docs/_themes/flask/layout.html create mode 100644 docs/_themes/flask/relations.html create mode 100644 docs/_themes/flask/static/flasky.css_t create mode 100644 docs/_themes/flask/static/small_flask.css create mode 100644 docs/_themes/flask/theme.conf create mode 100644 docs/_themes/flask_theme_support.py create mode 100644 docs/_themes/sphinx_rtd_theme/__init__.py create mode 100644 docs/_themes/sphinx_rtd_theme/breadcrumbs.html create mode 100644 docs/_themes/sphinx_rtd_theme/footer.html create mode 100644 docs/_themes/sphinx_rtd_theme/layout.html create mode 100644 docs/_themes/sphinx_rtd_theme/layout_old.html create mode 100644 docs/_themes/sphinx_rtd_theme/search.html create mode 100644 docs/_themes/sphinx_rtd_theme/searchbox.html create mode 100644 docs/_themes/sphinx_rtd_theme/static/css/badge_only.css create mode 100644 docs/_themes/sphinx_rtd_theme/static/css/theme.css create mode 100644 docs/_themes/sphinx_rtd_theme/static/fonts/FontAwesome.otf create mode 100644 docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.eot create mode 100644 docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg create mode 100644 docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.ttf create mode 100644 docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.woff create mode 100644 docs/_themes/sphinx_rtd_theme/static/js/theme.js create mode 100644 docs/_themes/sphinx_rtd_theme/theme.conf create mode 100644 docs/_themes/sphinx_rtd_theme/versions.html create mode 100644 docs/api/constants.rst create mode 100644 docs/api/index.rst create mode 100644 docs/api/resourcemanager.rst create mode 100644 docs/api/resources.rst create mode 100644 docs/api/visalibrarybase.rst create mode 100644 docs/architecture.rst create mode 100644 docs/backends.rst create mode 100644 docs/conf.py create mode 100644 docs/configuring.rst create mode 100644 docs/contributing.rst create mode 100644 docs/default.css create mode 100644 docs/example.rst create mode 100644 docs/faq.rst create mode 100644 docs/getting.rst create mode 100644 docs/getting_nivisa.rst create mode 100644 docs/index.rst create mode 100644 docs/make.bat create mode 100644 docs/migrating.rst create mode 100644 docs/names.rst create mode 100644 docs/resources.rst create mode 100644 docs/rvalues.rst create mode 100644 docs/shell.rst create mode 100644 docs/tutorial.rst create mode 100644 examples/itc4.py create mode 100644 examples/keithley2000.py create mode 100644 pyvisa/__init__.py create mode 100644 pyvisa/attributes.py create mode 100644 pyvisa/compat/__init__.py create mode 100644 pyvisa/compat/check_output.py create mode 100644 pyvisa/compat/nullhandler.py create mode 100644 pyvisa/compat/ordereddict.py create mode 100644 pyvisa/compat/struct.py create mode 100644 pyvisa/constants.py create mode 100644 pyvisa/ctwrapper/__init__.py create mode 100644 pyvisa/ctwrapper/cthelper.py create mode 100644 pyvisa/ctwrapper/functions.py create mode 100644 pyvisa/ctwrapper/highlevel.py create mode 100644 pyvisa/ctwrapper/types.py create mode 100644 pyvisa/errors.py create mode 100644 pyvisa/highlevel.py create mode 100644 pyvisa/resources/__init__.py create mode 100644 pyvisa/resources/firewire.py create mode 100644 pyvisa/resources/gpib.py create mode 100644 pyvisa/resources/messagebased.py create mode 100644 pyvisa/resources/pxi.py create mode 100644 pyvisa/resources/registerbased.py create mode 100644 pyvisa/resources/resource.py create mode 100644 pyvisa/resources/serial.py create mode 100644 pyvisa/resources/tcpip.py create mode 100644 pyvisa/resources/usb.py create mode 100644 pyvisa/resources/vxi.py create mode 100644 pyvisa/rname.py create mode 100644 pyvisa/shell.py create mode 100644 pyvisa/testsuite/__init__.py create mode 100644 pyvisa/testsuite/test_rname.py create mode 100644 pyvisa/testsuite/test_util.py create mode 100644 pyvisa/thirdparty/__init__.py create mode 100644 pyvisa/thirdparty/prettytable.py create mode 100644 pyvisa/util.py create mode 100644 setup.cfg create mode 100644 setup.py create mode 100644 tox.ini create mode 100644 visa.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ac02c9e --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*~ +__pycache__ +*egg-info* +*.pyc +.DS_Store +docs/_build/ +.idea +build/ +dist/ +MANIFEST +.tox +.coveragerc +# WebDAV file system cache files +.DAV/ +_test/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..28f009c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,20 @@ +language: python + +python: + - "2.6" + - "2.7" + - "3.2" + - "3.3" + - "3.4" + +install: + - if [ $TRAVIS_PYTHON_VERSION == '2.6' ]; then pip install unittest2; fi + - pip install coverage coveralls + +script: + - coverage run -p --source=pyvisa --omit="*test*","*compat*" setup.py test + - coverage combine + - coverage report -m + +after_script: + - coveralls --verbose diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..0c66f47 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,25 @@ +PyVISA 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 +* Martin Ritter +* Matthew94 +* Matthieu Dartiailh +* mordoror +* Tobias Müller +* Yves Delley + +If you think your name should be here, please let me know. diff --git a/CHANGES b/CHANGES new file mode 100644 index 0000000..3c74939 --- /dev/null +++ b/CHANGES @@ -0,0 +1,292 @@ +PyVISA Changelog +================ + + +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. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..fce5efa --- /dev/null +++ b/ChangeLog @@ -0,0 +1,995 @@ +2008-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. + + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3a87755 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2005-2014 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. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..dc2ef48 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,7 @@ +include README AUTHORS CHANGES LICENSE ChangeLog +recursive-include pyvisa * +recursive-include docs * +recursive-include examples * +prune docs/_build +prune docs/_themes/.git +global-exclude *.pyc *~ .DS_Store *__pycache__* *.pyo diff --git a/README b/README new file mode 100644 index 0000000..480038f --- /dev/null +++ b/README @@ -0,0 +1,69 @@ +PyVISA +====== + +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 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. However, you can use VISA with any language capable of calling functions in a DLL. +Python is such a language. + +.. _VISA: http://www.ivifoundation.org/specifications/default.aspx + + +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 +------------ + +- VISA (tested with NI-VISA 3.2, WinXP, from www.ni.com/visa) +- Python (tested with 2.6 and 3.2+) + + +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 diff --git a/docs/LICENSE b/docs/LICENSE new file mode 100644 index 0000000..271623f --- /dev/null +++ b/docs/LICENSE @@ -0,0 +1,23 @@ +The MIT License + +Copyright (c) 2005, 2006, 2007, 2008 + Torsten Bronger , + Gregor Thalhammer . + +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. diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..866ca77 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,153 @@ +# 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) . +# 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." diff --git a/docs/_static/logo-full.jpg b/docs/_static/logo-full.jpg new file mode 100644 index 0000000..763a12a Binary files /dev/null and b/docs/_static/logo-full.jpg differ diff --git a/docs/_templates/sidebarintro.html b/docs/_templates/sidebarintro.html new file mode 100644 index 0000000..92ebbc4 --- /dev/null +++ b/docs/_templates/sidebarintro.html @@ -0,0 +1,20 @@ +

About PyVISA

+Python wrapper for the Virtual Instrument Software Architechture library. +You are currently looking at the documentation of version {{ version }}. +

Other Formats

+

+ You can download the documentation in other formats as well: +

+ +

Useful Links

+ + + diff --git a/docs/_templates/sidebarlogo.html b/docs/_templates/sidebarlogo.html new file mode 100644 index 0000000..f220931 --- /dev/null +++ b/docs/_templates/sidebarlogo.html @@ -0,0 +1,23 @@ +

+ Logo +

+ +

About PyVISA

+Python wrapper for the Virtual Instrument Software Architechture library. +You are currently looking at the documentation of version {{ version }}. +

Other Formats

+

+ You can download the documentation in other formats as well: +

+ +

Useful Links

+ + diff --git a/docs/_themes/.gitignore b/docs/_themes/.gitignore new file mode 100644 index 0000000..66b6e4c --- /dev/null +++ b/docs/_themes/.gitignore @@ -0,0 +1,3 @@ +*.pyc +*.pyo +.DS_Store diff --git a/docs/_themes/LICENSE b/docs/_themes/LICENSE new file mode 100644 index 0000000..8daab7e --- /dev/null +++ b/docs/_themes/LICENSE @@ -0,0 +1,37 @@ +Copyright (c) 2010 by Armin Ronacher. + +Some rights reserved. + +Redistribution and use in source and binary forms of the theme, 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 names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +We kindly ask you to only use these themes in an unmodified manner just +for Flask and Flask-related products, not for unrelated projects. If you +like the visual style and want to use it for your own projects, please +consider making some larger changes to the themes (such as changing +font faces, sizes, colors or margins). + +THIS THEME 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 THEME, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/docs/_themes/README b/docs/_themes/README new file mode 100644 index 0000000..b3292bd --- /dev/null +++ b/docs/_themes/README @@ -0,0 +1,31 @@ +Flask Sphinx Styles +=================== + +This repository contains sphinx styles for Flask and Flask related +projects. To use this style in your Sphinx documentation, follow +this guide: + +1. put this folder as _themes into your docs folder. Alternatively + you can also use git submodules to check out the contents there. +2. add this to your conf.py: + + sys.path.append(os.path.abspath('_themes')) + html_theme_path = ['_themes'] + html_theme = 'flask' + +The following themes exist: + +- 'flask' - the standard flask documentation theme for large + projects +- 'flask_small' - small one-page theme. Intended to be used by + very small addon libraries for flask. + +The following options exist for the flask_small theme: + + [options] + index_logo = '' filename of a picture in _static + to be used as replacement for the + h1 in the index.rst file. + index_logo_height = 120px height of the index logo + github_fork = '' repository name on github for the + "fork me" badge diff --git a/docs/_themes/flask/layout.html b/docs/_themes/flask/layout.html new file mode 100644 index 0000000..4c79a9a --- /dev/null +++ b/docs/_themes/flask/layout.html @@ -0,0 +1,30 @@ +{%- extends "basic/layout.html" %} +{%- block extrahead %} + {{ super() }} + {% if theme_touch_icon %} + + {% endif %} + +{% endblock %} +{%- block relbar2 %} + {% if theme_github_fork %} + Fork me on GitHub + {% endif %} +{% endblock %} +{% block header %} + {{ super() }} + {% if pagename == 'index' %} +
+ {% endif %} +{% endblock %} +{%- block footer %} + + {% if pagename == 'index' %} +
+ {% endif %} +{%- endblock %} diff --git a/docs/_themes/flask/relations.html b/docs/_themes/flask/relations.html new file mode 100644 index 0000000..ed433fa --- /dev/null +++ b/docs/_themes/flask/relations.html @@ -0,0 +1,20 @@ + +

Related Topics

+ +{%- endfor %} +{%- if prev %} +

+ Previous
+ {{ prev.title }} +

+{%- endif %} +{%- if next %} +

+ Next
+ {{ next.title }} +

+{%- endif %} diff --git a/docs/_themes/flask/static/flasky.css_t b/docs/_themes/flask/static/flasky.css_t new file mode 100644 index 0000000..b5ca39b --- /dev/null +++ b/docs/_themes/flask/static/flasky.css_t @@ -0,0 +1,395 @@ +/* + * flasky.css_t + * ~~~~~~~~~~~~ + * + * :copyright: Copyright 2010 by Armin Ronacher. + * :license: Flask Design License, see LICENSE for details. + */ + +{% set page_width = '940px' %} +{% set sidebar_width = '220px' %} + +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: 'Georgia', serif; + font-size: 17px; + background-color: white; + color: #000; + margin: 0; + padding: 0; +} + +div.document { + width: {{ page_width }}; + margin: 30px auto 0 auto; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 {{ sidebar_width }}; +} + +div.sphinxsidebar { + width: {{ sidebar_width }}; +} + +hr { + border: 1px solid #B1B4B6; +} + +div.body { + background-color: #ffffff; + color: #3E4349; + padding: 0 30px 0 30px; +} + +img.floatingflask { + padding: 0 0 10px 10px; + float: right; +} + +div.footer { + width: {{ page_width }}; + margin: 20px auto 30px auto; + font-size: 14px; + color: #888; + text-align: right; +} + +div.footer a { + color: #888; +} + +div.related { + display: none; +} + +div.sphinxsidebar a { + color: #444; + text-decoration: none; + border-bottom: 1px dotted #999; +} + +div.sphinxsidebar a:hover { + border-bottom: 1px solid #999; +} + +div.sphinxsidebar { + font-size: 14px; + line-height: 1.5; +} + +div.sphinxsidebarwrapper { + padding: 18px 10px; +} + +div.sphinxsidebarwrapper p.logo { + padding: 0 0 20px 0; + margin: 0; + text-align: center; +} + +div.sphinxsidebar h3, +div.sphinxsidebar h4 { + font-family: 'Garamond', 'Georgia', serif; + color: #444; + font-size: 24px; + font-weight: normal; + margin: 0 0 5px 0; + padding: 0; +} + +div.sphinxsidebar h4 { + font-size: 20px; +} + +div.sphinxsidebar h3 a { + color: #444; +} + +div.sphinxsidebar p.logo a, +div.sphinxsidebar h3 a, +div.sphinxsidebar p.logo a:hover, +div.sphinxsidebar h3 a:hover { + border: none; +} + +div.sphinxsidebar p { + color: #555; + margin: 10px 0; +} + +div.sphinxsidebar ul { + margin: 10px 0; + padding: 0; + color: #000; +} + +div.sphinxsidebar input { + border: 1px solid #ccc; + font-family: 'Georgia', serif; + font-size: 1em; +} + +/* -- body styles ----------------------------------------------------------- */ + +a { + color: #004B6B; + text-decoration: underline; +} + +a:hover { + color: #6D4100; + text-decoration: underline; +} + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: 'Garamond', 'Georgia', serif; + font-weight: normal; + margin: 30px 0px 10px 0px; + padding: 0; +} + +{% if theme_index_logo %} +div.indexwrapper h1 { + text-indent: -999999px; + background: url({{ theme_index_logo }}) no-repeat center center; + height: {{ theme_index_logo_height }}; +} +{% endif %} + +div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } +div.body h2 { font-size: 180%; } +div.body h3 { font-size: 150%; } +div.body h4 { font-size: 130%; } +div.body h5 { font-size: 100%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #ddd; + padding: 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + color: #444; + background: #eaeaea; +} + +div.body p, div.body dd, div.body li { + line-height: 1.4em; +} + +div.admonition { + background: #fafafa; + margin: 20px -30px; + padding: 10px 30px; + border-top: 1px solid #ccc; + border-bottom: 1px solid #ccc; +} + +div.admonition tt.xref, div.admonition a tt { + border-bottom: 1px solid #fafafa; +} + +dd div.admonition { + margin-left: -60px; + padding-left: 60px; +} + +div.admonition p.admonition-title { + font-family: 'Garamond', 'Georgia', serif; + font-weight: normal; + font-size: 24px; + margin: 0 0 10px 0; + padding: 0; + line-height: 1; +} + +div.admonition p.last { + margin-bottom: 0; +} + +div.highlight { + background-color: white; +} + +dt:target, .highlight { + background: #FAF3E8; +} + +div.note { + background-color: #eee; + border: 1px solid #ccc; +} + +div.seealso { + background-color: #ffc; + border: 1px solid #ff6; +} + +div.topic { + background-color: #eee; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre, tt { + font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; + font-size: 0.9em; +} + +img.screenshot { +} + +tt.descname, tt.descclassname { + font-size: 0.95em; +} + +tt.descname { + padding-right: 0.08em; +} + +img.screenshot { + -moz-box-shadow: 2px 2px 4px #eee; + -webkit-box-shadow: 2px 2px 4px #eee; + box-shadow: 2px 2px 4px #eee; +} + +table.docutils { + border: 1px solid #888; + -moz-box-shadow: 2px 2px 4px #eee; + -webkit-box-shadow: 2px 2px 4px #eee; + box-shadow: 2px 2px 4px #eee; +} + +table.docutils td, table.docutils th { + border: 1px solid #888; + padding: 0.25em 0.7em; +} + +table.field-list, table.footnote { + border: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + +table.footnote { + margin: 15px 0; + width: 100%; + border: 1px solid #eee; + background: #fdfdfd; + font-size: 0.9em; +} + +table.footnote + table.footnote { + margin-top: -15px; + border-top: none; +} + +table.field-list th { + padding: 0 0.8em 0 0; +} + +table.field-list td { + padding: 0; +} + +table.footnote td.label { + width: 0px; + padding: 0.3em 0 0.3em 0.5em; +} + +table.footnote td { + padding: 0.3em 0.5em; +} + +dl { + margin: 0; + padding: 0; +} + +dl dd { + margin-left: 30px; +} + +blockquote { + margin: 0 0 0 30px; + padding: 0; +} + +ul, ol { + margin: 10px 0 10px 30px; + padding: 0; +} + +pre { + background: #eee; + padding: 7px 30px; + margin: 15px -30px; + line-height: 1.3em; +} + +dl pre, blockquote pre, li pre { + margin-left: -60px; + padding-left: 60px; +} + +dl dl pre { + margin-left: -90px; + padding-left: 90px; +} + +tt { + background-color: #ecf0f3; + color: #222; + /* padding: 1px 2px; */ +} + +tt.xref, a tt { + background-color: #FBFBFB; + border-bottom: 1px solid white; +} + +a.reference { + text-decoration: none; + border-bottom: 1px dotted #004B6B; +} + +a.reference:hover { + border-bottom: 1px solid #6D4100; +} + +a.footnote-reference { + text-decoration: none; + font-size: 0.7em; + vertical-align: top; + border-bottom: 1px dotted #004B6B; +} + +a.footnote-reference:hover { + border-bottom: 1px solid #6D4100; +} + +a:hover tt { + background: #EEE; +} diff --git a/docs/_themes/flask/static/small_flask.css b/docs/_themes/flask/static/small_flask.css new file mode 100644 index 0000000..1c6df30 --- /dev/null +++ b/docs/_themes/flask/static/small_flask.css @@ -0,0 +1,70 @@ +/* + * small_flask.css_t + * ~~~~~~~~~~~~~~~~~ + * + * :copyright: Copyright 2010 by Armin Ronacher. + * :license: Flask Design License, see LICENSE for details. + */ + +body { + margin: 0; + padding: 20px 30px; +} + +div.documentwrapper { + float: none; + background: white; +} + +div.sphinxsidebar { + display: block; + float: none; + width: 102.5%; + margin: 50px -30px -20px -30px; + padding: 10px 20px; + background: #333; + color: white; +} + +div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, +div.sphinxsidebar h3 a { + color: white; +} + +div.sphinxsidebar a { + color: #aaa; +} + +div.sphinxsidebar p.logo { + display: none; +} + +div.document { + width: 100%; + margin: 0; +} + +div.related { + display: block; + margin: 0; + padding: 10px 0 20px 0; +} + +div.related ul, +div.related ul li { + margin: 0; + padding: 0; +} + +div.footer { + display: none; +} + +div.bodywrapper { + margin: 0; +} + +div.body { + min-height: 0; + padding: 0; +} diff --git a/docs/_themes/flask/theme.conf b/docs/_themes/flask/theme.conf new file mode 100644 index 0000000..4313e2a --- /dev/null +++ b/docs/_themes/flask/theme.conf @@ -0,0 +1,10 @@ +[theme] +inherit = basic +stylesheet = flasky.css +pygments_style = flask_theme_support.FlaskyStyle + +[options] +index_logo = '' +index_logo_height = 120px +touch_icon = +github_fork = hgrecco/pyvisa diff --git a/docs/_themes/flask_theme_support.py b/docs/_themes/flask_theme_support.py new file mode 100644 index 0000000..33f4744 --- /dev/null +++ b/docs/_themes/flask_theme_support.py @@ -0,0 +1,86 @@ +# flasky extensions. flasky pygments style based on tango style +from pygments.style import Style +from pygments.token import Keyword, Name, Comment, String, Error, \ + Number, Operator, Generic, Whitespace, Punctuation, Other, Literal + + +class FlaskyStyle(Style): + background_color = "#f8f8f8" + default_style = "" + + styles = { + # No corresponding class for the following: + #Text: "", # class: '' + Whitespace: "underline #f8f8f8", # class: 'w' + Error: "#a40000 border:#ef2929", # class: 'err' + Other: "#000000", # class 'x' + + Comment: "italic #8f5902", # class: 'c' + Comment.Preproc: "noitalic", # class: 'cp' + + Keyword: "bold #004461", # class: 'k' + Keyword.Constant: "bold #004461", # class: 'kc' + Keyword.Declaration: "bold #004461", # class: 'kd' + Keyword.Namespace: "bold #004461", # class: 'kn' + Keyword.Pseudo: "bold #004461", # class: 'kp' + Keyword.Reserved: "bold #004461", # class: 'kr' + Keyword.Type: "bold #004461", # class: 'kt' + + Operator: "#582800", # class: 'o' + Operator.Word: "bold #004461", # class: 'ow' - like keywords + + Punctuation: "bold #000000", # class: 'p' + + # because special names such as Name.Class, Name.Function, etc. + # are not recognized as such later in the parsing, we choose them + # to look the same as ordinary variables. + Name: "#000000", # class: 'n' + Name.Attribute: "#c4a000", # class: 'na' - to be revised + Name.Builtin: "#004461", # class: 'nb' + Name.Builtin.Pseudo: "#3465a4", # class: 'bp' + Name.Class: "#000000", # class: 'nc' - to be revised + Name.Constant: "#000000", # class: 'no' - to be revised + Name.Decorator: "#888", # class: 'nd' - to be revised + Name.Entity: "#ce5c00", # class: 'ni' + Name.Exception: "bold #cc0000", # class: 'ne' + Name.Function: "#000000", # class: 'nf' + Name.Property: "#000000", # class: 'py' + Name.Label: "#f57900", # class: 'nl' + Name.Namespace: "#000000", # class: 'nn' - to be revised + Name.Other: "#000000", # class: 'nx' + Name.Tag: "bold #004461", # class: 'nt' - like a keyword + Name.Variable: "#000000", # class: 'nv' - to be revised + Name.Variable.Class: "#000000", # class: 'vc' - to be revised + Name.Variable.Global: "#000000", # class: 'vg' - to be revised + Name.Variable.Instance: "#000000", # class: 'vi' - to be revised + + Number: "#990000", # class: 'm' + + Literal: "#000000", # class: 'l' + Literal.Date: "#000000", # class: 'ld' + + String: "#4e9a06", # class: 's' + String.Backtick: "#4e9a06", # class: 'sb' + String.Char: "#4e9a06", # class: 'sc' + String.Doc: "italic #8f5902", # class: 'sd' - like a comment + String.Double: "#4e9a06", # class: 's2' + String.Escape: "#4e9a06", # class: 'se' + String.Heredoc: "#4e9a06", # class: 'sh' + String.Interpol: "#4e9a06", # class: 'si' + String.Other: "#4e9a06", # class: 'sx' + String.Regex: "#4e9a06", # class: 'sr' + String.Single: "#4e9a06", # class: 's1' + String.Symbol: "#4e9a06", # class: 'ss' + + Generic: "#000000", # class: 'g' + Generic.Deleted: "#a40000", # class: 'gd' + Generic.Emph: "italic #000000", # class: 'ge' + Generic.Error: "#ef2929", # class: 'gr' + Generic.Heading: "bold #000080", # class: 'gh' + Generic.Inserted: "#00A000", # class: 'gi' + Generic.Output: "#888", # class: 'go' + Generic.Prompt: "#745334", # class: 'gp' + Generic.Strong: "bold #000000", # class: 'gs' + Generic.Subheading: "bold #800080", # class: 'gu' + Generic.Traceback: "bold #a40000", # class: 'gt' + } diff --git a/docs/_themes/sphinx_rtd_theme/__init__.py b/docs/_themes/sphinx_rtd_theme/__init__.py new file mode 100644 index 0000000..1440863 --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/__init__.py @@ -0,0 +1,17 @@ +"""Sphinx ReadTheDocs theme. + +From https://github.com/ryan-roemer/sphinx-bootstrap-theme. + +""" +import os + +VERSION = (0, 1, 5) + +__version__ = ".".join(str(v) for v in VERSION) +__version_full__ = __version__ + + +def get_html_theme_path(): + """Return list of HTML theme paths.""" + cur_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) + return cur_dir diff --git a/docs/_themes/sphinx_rtd_theme/breadcrumbs.html b/docs/_themes/sphinx_rtd_theme/breadcrumbs.html new file mode 100644 index 0000000..d9b2937 --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/breadcrumbs.html @@ -0,0 +1,19 @@ +
+ +
+
diff --git a/docs/_themes/sphinx_rtd_theme/footer.html b/docs/_themes/sphinx_rtd_theme/footer.html new file mode 100644 index 0000000..21a6b55 --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/footer.html @@ -0,0 +1,32 @@ +
+ {% if next or prev %} + + {% endif %} + +
+ +
+

+ {%- if show_copyright %} + {%- if hasdoc('copyright') %} + {% trans path=pathto('copyright'), copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %} + {%- else %} + {% trans copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %} + {%- endif %} + {%- endif %} + + {%- if last_updated %} + {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %} + {%- endif %} +

+
+ + {% trans %}Sphinx theme provided by Read the Docs{% endtrans %} +
diff --git a/docs/_themes/sphinx_rtd_theme/layout.html b/docs/_themes/sphinx_rtd_theme/layout.html new file mode 100644 index 0000000..552c77f --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/layout.html @@ -0,0 +1,161 @@ +{# TEMPLATE VAR SETTINGS #} +{%- set url_root = pathto('', 1) %} +{%- if url_root == '#' %}{% set url_root = '' %}{% endif %} +{%- if not embedded and docstitle %} + {%- set titlesuffix = " — "|safe + docstitle|e %} +{%- else %} + {%- set titlesuffix = "" %} +{%- endif %} + + + + + + + + {% block htmltitle %} + {{ title|striptags|e }}{{ titlesuffix }} + {% endblock %} + + {# FAVICON #} + {% if favicon %} + + {% endif %} + + {# CSS #} + + + {# JS #} + {% if not embedded %} + + + {%- for scriptfile in script_files %} + + {%- endfor %} + + {% if use_opensearch %} + + {% endif %} + + {% endif %} + + {# RTD hosts these file themselves, so just load on non RTD builds #} + {% if not READTHEDOCS %} + + + {% endif %} + + {# STICKY NAVIGATION #} + {% if theme_sticky_navigation %} + + {% endif %} + + {% for cssfile in css_files %} + + {% endfor %} + + {%- block linktags %} + {%- if hasdoc('about') %} + + {%- endif %} + {%- if hasdoc('genindex') %} + + {%- endif %} + {%- if hasdoc('search') %} + + {%- endif %} + {%- if hasdoc('copyright') %} + + {%- endif %} + + {%- if parents %} + + {%- endif %} + {%- if next %} + + {%- endif %} + {%- if prev %} + + {%- endif %} + {%- endblock %} + {%- block extrahead %} {% endblock %} + + + + + + + +
+ + {# SIDE NAV, TOGGLES ON MOBILE #} + + +
+ + {# MOBILE NAV, TRIGGLES SIDE NAV ON TOGGLE #} + + + + {# PAGE CONTENT #} +
+
+ {% include "breadcrumbs.html" %} +
+ {% block body %}{% endblock %} +
+ {% include "footer.html" %} +
+
+ +
+ +
+ {% include "versions.html" %} + + {% if theme_github_fork %} + Fork me on GitHub + {% endif %} + + + diff --git a/docs/_themes/sphinx_rtd_theme/layout_old.html b/docs/_themes/sphinx_rtd_theme/layout_old.html new file mode 100644 index 0000000..deb8df2 --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/layout_old.html @@ -0,0 +1,205 @@ +{# + basic/layout.html + ~~~~~~~~~~~~~~~~~ + + Master layout template for Sphinx themes. + + :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +#} +{%- block doctype -%} + +{%- endblock %} +{%- set reldelim1 = reldelim1 is not defined and ' »' or reldelim1 %} +{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %} +{%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and + (sidebars != []) %} +{%- set url_root = pathto('', 1) %} +{# XXX necessary? #} +{%- if url_root == '#' %}{% set url_root = '' %}{% endif %} +{%- if not embedded and docstitle %} + {%- set titlesuffix = " — "|safe + docstitle|e %} +{%- else %} + {%- set titlesuffix = "" %} +{%- endif %} + +{%- macro relbar() %} + +{%- endmacro %} + +{%- macro sidebar() %} + {%- if render_sidebar %} +
+
+ {%- block sidebarlogo %} + {%- if logo %} + + {%- endif %} + {%- endblock %} + {%- if sidebars != None %} + {#- new style sidebar: explicitly include/exclude templates #} + {%- for sidebartemplate in sidebars %} + {%- include sidebartemplate %} + {%- endfor %} + {%- else %} + {#- old style sidebars: using blocks -- should be deprecated #} + {%- block sidebartoc %} + {%- include "localtoc.html" %} + {%- endblock %} + {%- block sidebarrel %} + {%- include "relations.html" %} + {%- endblock %} + {%- block sidebarsourcelink %} + {%- include "sourcelink.html" %} + {%- endblock %} + {%- if customsidebar %} + {%- include customsidebar %} + {%- endif %} + {%- block sidebarsearch %} + {%- include "searchbox.html" %} + {%- endblock %} + {%- endif %} +
+
+ {%- endif %} +{%- endmacro %} + +{%- macro script() %} + + {%- for scriptfile in script_files %} + + {%- endfor %} +{%- endmacro %} + +{%- macro css() %} + + + {%- for cssfile in css_files %} + + {%- endfor %} +{%- endmacro %} + + + + + {{ metatags }} + {%- block htmltitle %} + {{ title|striptags|e }}{{ titlesuffix }} + {%- endblock %} + {{ css() }} + {%- if not embedded %} + {{ script() }} + {%- if use_opensearch %} + + {%- endif %} + {%- if favicon %} + + {%- endif %} + {%- endif %} +{%- block linktags %} + {%- if hasdoc('about') %} + + {%- endif %} + {%- if hasdoc('genindex') %} + + {%- endif %} + {%- if hasdoc('search') %} + + {%- endif %} + {%- if hasdoc('copyright') %} + + {%- endif %} + + {%- if parents %} + + {%- endif %} + {%- if next %} + + {%- endif %} + {%- if prev %} + + {%- endif %} +{%- endblock %} +{%- block extrahead %} {% endblock %} + + +{%- block header %}{% endblock %} + +{%- block relbar1 %}{{ relbar() }}{% endblock %} + +{%- block content %} + {%- block sidebar1 %} {# possible location for sidebar #} {% endblock %} + +
+ {%- block document %} +
+ {%- if render_sidebar %} +
+ {%- endif %} +
+ {% block body %} {% endblock %} +
+ {%- if render_sidebar %} +
+ {%- endif %} +
+ {%- endblock %} + + {%- block sidebar2 %}{{ sidebar() }}{% endblock %} +
+
+{%- endblock %} + +{%- block relbar2 %}{{ relbar() }}{% endblock %} + +{%- block footer %} + +

asdf asdf asdf asdf 22

+{%- endblock %} + + + diff --git a/docs/_themes/sphinx_rtd_theme/search.html b/docs/_themes/sphinx_rtd_theme/search.html new file mode 100644 index 0000000..d8bbe69 --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/search.html @@ -0,0 +1,50 @@ +{# + basic/search.html + ~~~~~~~~~~~~~~~~~ + + Template for the search page. + + :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +#} +{%- extends "layout.html" %} +{% set title = _('Search') %} +{% set script_files = script_files + ['_static/searchtools.js'] %} +{% block extrahead %} + + {# this is used when loading the search index using $.ajax fails, + such as on Chrome for documents on localhost #} + + {{ super() }} +{% endblock %} +{% block body %} + + + {% if search_performed %} +

{{ _('Search Results') }}

+ {% if not search_results %} +

{{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}

+ {% endif %} + {% endif %} +
+ {% if search_results %} +
    + {% for href, caption, context in search_results %} +
  • + {{ caption }} +

    {{ context|e }}

    +
  • + {% endfor %} +
+ {% endif %} +
+{% endblock %} diff --git a/docs/_themes/sphinx_rtd_theme/searchbox.html b/docs/_themes/sphinx_rtd_theme/searchbox.html new file mode 100644 index 0000000..24418d3 --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/searchbox.html @@ -0,0 +1,7 @@ +
+
+ + + +
+
diff --git a/docs/_themes/sphinx_rtd_theme/static/css/badge_only.css b/docs/_themes/sphinx_rtd_theme/static/css/badge_only.css new file mode 100644 index 0000000..6f7bbe7 --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/static/css/badge_only.css @@ -0,0 +1,224 @@ +.font-smooth, .fa:before { + -webkit-font-smoothing: antialiased; +} + +.clearfix { + *zoom: 1; +} +.clearfix:before, .clearfix:after { + display: table; + content: ""; +} +.clearfix:after { + clear: both; +} + +@font-face { + font-family: FontAwesome; + font-weight: normal; + font-style: normal; + src: url("../font/fontawesome_webfont.eot"); + src: url("../font/fontawesome_webfont.eot?#iefix") format("embedded-opentype"), url("../font/fontawesome_webfont.woff") format("woff"), url("../font/fontawesome_webfont.ttf") format("truetype"), url("../font/fontawesome_webfont.svg#FontAwesome") format("svg"); +} + +.fa:before { + display: inline-block; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + line-height: 1; + text-decoration: inherit; +} + +a .fa { + display: inline-block; + text-decoration: inherit; +} + +li .fa { + display: inline-block; +} +li .fa-large:before, +li .fa-large:before { + /* 1.5 increased font size for fa-large * 1.25 width */ + width: 1.875em; +} + +ul.fas { + list-style-type: none; + margin-left: 2em; + text-indent: -0.8em; +} +ul.fas li .fa { + width: 0.8em; +} +ul.fas li .fa-large:before, +ul.fas li .fa-large:before { + /* 1.5 increased font size for fa-large * 1.25 width */ + vertical-align: baseline; +} + +.fa-book:before { + content: "\f02d"; +} + +.icon-book:before { + content: "\f02d"; +} + +.fa-caret-down:before { + content: "\f0d7"; +} + +.icon-caret-down:before { + content: "\f0d7"; +} + +.fa-caret-up:before { + content: "\f0d8"; +} + +.icon-caret-up:before { + content: "\f0d8"; +} + +.fa-caret-left:before { + content: "\f0d9"; +} + +.icon-caret-left:before { + content: "\f0d9"; +} + +.fa-caret-right:before { + content: "\f0da"; +} + +.icon-caret-right:before { + content: "\f0da"; +} + +.rst-versions { + position: fixed; + bottom: 0; + left: 0; + width: 300px; + color: #fcfcfc; + background: #1f1d1d; + border-top: solid 10px #343131; + font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; + z-index: 400; +} +.rst-versions a { + color: #2980b9; + text-decoration: none; +} +.rst-versions .rst-badge-small { + display: none; +} +.rst-versions .rst-current-version { + padding: 12px; + background-color: #272525; + display: block; + text-align: right; + font-size: 90%; + cursor: pointer; + color: #27ae60; + *zoom: 1; +} +.rst-versions .rst-current-version:before, .rst-versions .rst-current-version:after { + display: table; + content: ""; +} +.rst-versions .rst-current-version:after { + clear: both; +} +.rst-versions .rst-current-version .fa { + color: #fcfcfc; +} +.rst-versions .rst-current-version .fa-book { + float: left; +} +.rst-versions .rst-current-version .icon-book { + float: left; +} +.rst-versions .rst-current-version.rst-out-of-date { + background-color: #e74c3c; + color: white; +} +.rst-versions .rst-current-version.rst-active-old-version { + background-color: #f1c40f; + color: black; +} +.rst-versions.shift-up .rst-other-versions { + display: block; +} +.rst-versions .rst-other-versions { + font-size: 90%; + padding: 12px; + color: gray; + display: none; +} +.rst-versions .rst-other-versions hr { + display: block; + height: 1px; + border: 0; + margin: 20px 0; + padding: 0; + border-top: solid 1px #413d3d; +} +.rst-versions .rst-other-versions dd { + display: inline-block; + margin: 0; +} +.rst-versions .rst-other-versions dd a { + display: inline-block; + padding: 6px; + color: #fcfcfc; +} +.rst-versions.rst-badge { + width: auto; + bottom: 20px; + right: 20px; + left: auto; + border: none; + max-width: 300px; +} +.rst-versions.rst-badge .icon-book { + float: none; +} +.rst-versions.rst-badge .fa-book { + float: none; +} +.rst-versions.rst-badge.shift-up .rst-current-version { + text-align: right; +} +.rst-versions.rst-badge.shift-up .rst-current-version .fa-book { + float: left; +} +.rst-versions.rst-badge.shift-up .rst-current-version .icon-book { + float: left; +} +.rst-versions.rst-badge .rst-current-version { + width: auto; + height: 30px; + line-height: 30px; + padding: 0 6px; + display: block; + text-align: center; +} + +@media screen and (max-width: 768px) { + .rst-versions { + width: 85%; + display: none; + } + .rst-versions.shift { + display: block; + } + + img { + width: 100%; + height: auto; + } +} diff --git a/docs/_themes/sphinx_rtd_theme/static/css/theme.css b/docs/_themes/sphinx_rtd_theme/static/css/theme.css new file mode 100644 index 0000000..9f485d0 --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/static/css/theme.css @@ -0,0 +1,4725 @@ +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { + display: block; +} + +audio, canvas, video { + display: inline-block; + *display: inline; + *zoom: 1; +} + +audio:not([controls]) { + display: none; +} + +[hidden] { + display: none; +} + +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +html { + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +body { + margin: 0; +} + +a:hover, a:active { + outline: 0; +} + +abbr[title] { + border-bottom: 1px dotted; +} + +b, strong { + font-weight: bold; +} + +blockquote { + margin: 0; +} + +dfn { + font-style: italic; +} + +hr { + display: block; + height: 1px; + border: 0; + border-top: 1px solid #cccccc; + margin: 20px 0; + padding: 0; +} + +ins { + background: #ffff99; + color: black; + text-decoration: none; +} + +mark { + background: yellow; + color: black; + font-style: italic; + font-weight: bold; +} + +pre, code, .rst-content tt, kbd, samp { + font-family: monospace, serif; + _font-family: "courier new", monospace; + font-size: 1em; +} + +pre { + white-space: pre; +} + +q { + quotes: none; +} + +q:before, q:after { + content: ""; + content: none; +} + +small { + font-size: 85%; +} + +sub, sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +ul, ol, dl { + margin: 0; + padding: 0; + list-style: none; + list-style-image: none; +} + +li { + list-style: none; +} + +dd { + margin: 0; +} + +img { + border: 0; + -ms-interpolation-mode: bicubic; + vertical-align: middle; + max-width: 100%; +} + +svg:not(:root) { + overflow: hidden; +} + +figure { + margin: 0; +} + +form { + margin: 0; +} + +fieldset { + border: 0; + margin: 0; + padding: 0; +} + +label { + cursor: pointer; +} + +legend { + border: 0; + *margin-left: -7px; + padding: 0; + white-space: normal; +} + +button, input, select, textarea { + font-size: 100%; + margin: 0; + vertical-align: baseline; + *vertical-align: middle; +} + +button, input { + line-height: normal; +} + +button, input[type="button"], input[type="reset"], input[type="submit"] { + cursor: pointer; + -webkit-appearance: button; + *overflow: visible; +} + +button[disabled], input[disabled] { + cursor: default; +} + +input[type="checkbox"], input[type="radio"] { + box-sizing: border-box; + padding: 0; + *width: 13px; + *height: 13px; +} + +input[type="search"] { + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} + +input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none; +} + +button::-moz-focus-inner, input::-moz-focus-inner { + border: 0; + padding: 0; +} + +textarea { + overflow: auto; + vertical-align: top; + resize: vertical; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +td { + vertical-align: top; +} + +.chromeframe { + margin: 0.2em 0; + background: #cccccc; + color: black; + padding: 0.2em 0; +} + +.ir { + display: block; + border: 0; + text-indent: -999em; + overflow: hidden; + background-color: transparent; + background-repeat: no-repeat; + text-align: left; + direction: ltr; + *line-height: 0; +} + +.ir br { + display: none; +} + +.hidden { + display: none !important; + visibility: hidden; +} + +.visuallyhidden { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} + +.visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { + clip: auto; + height: auto; + margin: 0; + overflow: visible; + position: static; + width: auto; +} + +.invisible { + visibility: hidden; +} + +.relative { + position: relative; +} + +big, small { + font-size: 100%; +} + +@media print { + html, body, section { + background: none !important; + } + + * { + box-shadow: none !important; + text-shadow: none !important; + filter: none !important; + -ms-filter: none !important; + } + + a, a:visited { + text-decoration: underline; + } + + .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { + content: ""; + } + + pre, blockquote { + page-break-inside: avoid; + } + + thead { + display: table-header-group; + } + + tr, img { + page-break-inside: avoid; + } + + img { + max-width: 100% !important; + } + + @page { + margin: 0.5cm; +} + + p, h2, h3 { + orphans: 3; + widows: 3; + } + + h2, h3 { + page-break-after: avoid; + } +} +.font-smooth, .wy-alert, .rst-content .note, .rst-content .attention, .rst-content .caution, .rst-content .danger, .rst-content .error, .rst-content .hint, .rst-content .important, .rst-content .tip, .rst-content .warning, .rst-content .seealso, .btn, input[type="text"], input[type="password"], input[type="email"], input[type="url"], input[type="date"], input[type="month"], input[type="time"], input[type="datetime"], input[type="datetime-local"], input[type="week"], input[type="number"], input[type="search"], input[type="tel"], input[type="color"], select, textarea, .wy-tag-input-group, .wy-menu-vertical li.on a, .wy-menu-vertical li.current > a, .wy-side-nav-search > a, .wy-side-nav-search .wy-dropdown > a, .wy-nav-top a { + -webkit-font-smoothing: antialiased; +} + +.clearfix { + *zoom: 1; +} +.clearfix:before, .clearfix:after { + display: table; + content: ""; +} +.clearfix:after { + clear: both; +} + +/*! + * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */ +/* FONT PATH + * -------------------------- */ +@font-face { + font-family: 'FontAwesome'; + src: url("../fonts/fontawesome-webfont.eot?v=4.0.3"); + src: url("../fonts/fontawesome-webfont.eot?#iefix&v=4.0.3") format("embedded-opentype"), url("../fonts/fontawesome-webfont.woff?v=4.0.3") format("woff"), url("../fonts/fontawesome-webfont.ttf?v=4.0.3") format("truetype"), url("../fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular") format("svg"); + font-weight: normal; + font-style: normal; +} + +.fa, .wy-dropdown .caret, .wy-inline-validate.wy-inline-validate-success .wy-input-context, .wy-inline-validate.wy-inline-validate-danger .wy-input-context, .wy-inline-validate.wy-inline-validate-warning .wy-input-context, .wy-inline-validate.wy-inline-validate-info .wy-input-context, .wy-tag-input-group .wy-tag .wy-tag-remove, .rst-content .admonition-title, .rst-content h1 .headerlink, .rst-content h2 .headerlink, .rst-content h3 .headerlink, .rst-content h4 .headerlink, .rst-content h5 .headerlink, .rst-content h6 .headerlink, .rst-content dl dt .headerlink, .icon { + display: inline-block; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* makes the font 33% larger relative to the icon container */ +.fa-lg { + font-size: 1.33333em; + line-height: 0.75em; + vertical-align: -15%; +} + +.fa-2x { + font-size: 2em; +} + +.fa-3x { + font-size: 3em; +} + +.fa-4x { + font-size: 4em; +} + +.fa-5x { + font-size: 5em; +} + +.fa-fw { + width: 1.28571em; + text-align: center; +} + +.fa-ul { + padding-left: 0; + margin-left: 2.14286em; + list-style-type: none; +} +.fa-ul > li { + position: relative; +} + +.fa-li { + position: absolute; + left: -2.14286em; + width: 2.14286em; + top: 0.14286em; + text-align: center; +} +.fa-li.fa-lg { + left: -1.85714em; +} + +.fa-border { + padding: .2em .25em .15em; + border: solid 0.08em #eeeeee; + border-radius: .1em; +} + +.pull-right { + float: right; +} + +.pull-left { + float: left; +} + +.fa.pull-left, .wy-dropdown .pull-left.caret, .wy-inline-validate.wy-inline-validate-success .pull-left.wy-input-context, .wy-inline-validate.wy-inline-validate-danger .pull-left.wy-input-context, .wy-inline-validate.wy-inline-validate-warning .pull-left.wy-input-context, .wy-inline-validate.wy-inline-validate-info .pull-left.wy-input-context, .wy-tag-input-group .wy-tag .pull-left.wy-tag-remove, .rst-content .pull-left.admonition-title, .rst-content h1 .pull-left.headerlink, .rst-content h2 .pull-left.headerlink, .rst-content h3 .pull-left.headerlink, .rst-content h4 .pull-left.headerlink, .rst-content h5 .pull-left.headerlink, .rst-content h6 .pull-left.headerlink, .rst-content dl dt .pull-left.headerlink, .pull-left.icon { + margin-right: .3em; +} +.fa.pull-right, .wy-dropdown .pull-right.caret, .wy-inline-validate.wy-inline-validate-success .pull-right.wy-input-context, .wy-inline-validate.wy-inline-validate-danger .pull-right.wy-input-context, .wy-inline-validate.wy-inline-validate-warning .pull-right.wy-input-context, .wy-inline-validate.wy-inline-validate-info .pull-right.wy-input-context, .wy-tag-input-group .wy-tag .pull-right.wy-tag-remove, .rst-content .pull-right.admonition-title, .rst-content h1 .pull-right.headerlink, .rst-content h2 .pull-right.headerlink, .rst-content h3 .pull-right.headerlink, .rst-content h4 .pull-right.headerlink, .rst-content h5 .pull-right.headerlink, .rst-content h6 .pull-right.headerlink, .rst-content dl dt .pull-right.headerlink, .pull-right.icon { + margin-left: .3em; +} + +.fa-spin { + -webkit-animation: spin 2s infinite linear; + -moz-animation: spin 2s infinite linear; + -o-animation: spin 2s infinite linear; + animation: spin 2s infinite linear; +} + +@-moz-keyframes spin { + 0% { + -moz-transform: rotate(0deg); + } + + 100% { + -moz-transform: rotate(359deg); + } +} + +@-webkit-keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + } + + 100% { + -webkit-transform: rotate(359deg); + } +} + +@-o-keyframes spin { + 0% { + -o-transform: rotate(0deg); + } + + 100% { + -o-transform: rotate(359deg); + } +} + +@-ms-keyframes spin { + 0% { + -ms-transform: rotate(0deg); + } + + 100% { + -ms-transform: rotate(359deg); + } +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(359deg); + } +} + +.fa-rotate-90 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation); + -webkit-transform: rotate(90deg); + -moz-transform: rotate(90deg); + -ms-transform: rotate(90deg); + -o-transform: rotate(90deg); + transform: rotate(90deg); +} + +.fa-rotate-180 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation); + -webkit-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -o-transform: rotate(180deg); + transform: rotate(180deg); +} + +.fa-rotate-270 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation); + -webkit-transform: rotate(270deg); + -moz-transform: rotate(270deg); + -ms-transform: rotate(270deg); + -o-transform: rotate(270deg); + transform: rotate(270deg); +} + +.fa-flip-horizontal { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation); + -webkit-transform: scale(-1, 1); + -moz-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + -o-transform: scale(-1, 1); + transform: scale(-1, 1); +} + +.fa-flip-vertical { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation); + -webkit-transform: scale(1, -1); + -moz-transform: scale(1, -1); + -ms-transform: scale(1, -1); + -o-transform: scale(1, -1); + transform: scale(1, -1); +} + +.fa-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle; +} + +.fa-stack-1x, .fa-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center; +} + +.fa-stack-1x { + line-height: inherit; +} + +.fa-stack-2x { + font-size: 2em; +} + +.fa-inverse { + color: white; +} + +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen + readers do not read off random characters that represent icons */ +.fa-glass:before { + content: "\f000"; +} + +.fa-music:before { + content: "\f001"; +} + +.fa-search:before, .icon-search:before { + content: "\f002"; +} + +.fa-envelope-o:before { + content: "\f003"; +} + +.fa-heart:before { + content: "\f004"; +} + +.fa-star:before { + content: "\f005"; +} + +.fa-star-o:before { + content: "\f006"; +} + +.fa-user:before { + content: "\f007"; +} + +.fa-film:before { + content: "\f008"; +} + +.fa-th-large:before { + content: "\f009"; +} + +.fa-th:before { + content: "\f00a"; +} + +.fa-th-list:before { + content: "\f00b"; +} + +.fa-check:before { + content: "\f00c"; +} + +.fa-times:before, .wy-tag-input-group .wy-tag .wy-tag-remove:before { + content: "\f00d"; +} + +.fa-search-plus:before { + content: "\f00e"; +} + +.fa-search-minus:before { + content: "\f010"; +} + +.fa-power-off:before { + content: "\f011"; +} + +.fa-signal:before { + content: "\f012"; +} + +.fa-gear:before, +.fa-cog:before { + content: "\f013"; +} + +.fa-trash-o:before { + content: "\f014"; +} + +.fa-home:before, .icon-home:before { + content: "\f015"; +} + +.fa-file-o:before { + content: "\f016"; +} + +.fa-clock-o:before { + content: "\f017"; +} + +.fa-road:before { + content: "\f018"; +} + +.fa-download:before { + content: "\f019"; +} + +.fa-arrow-circle-o-down:before { + content: "\f01a"; +} + +.fa-arrow-circle-o-up:before { + content: "\f01b"; +} + +.fa-inbox:before { + content: "\f01c"; +} + +.fa-play-circle-o:before { + content: "\f01d"; +} + +.fa-rotate-right:before, +.fa-repeat:before { + content: "\f01e"; +} + +.fa-refresh:before { + content: "\f021"; +} + +.fa-list-alt:before { + content: "\f022"; +} + +.fa-lock:before { + content: "\f023"; +} + +.fa-flag:before { + content: "\f024"; +} + +.fa-headphones:before { + content: "\f025"; +} + +.fa-volume-off:before { + content: "\f026"; +} + +.fa-volume-down:before { + content: "\f027"; +} + +.fa-volume-up:before { + content: "\f028"; +} + +.fa-qrcode:before { + content: "\f029"; +} + +.fa-barcode:before { + content: "\f02a"; +} + +.fa-tag:before { + content: "\f02b"; +} + +.fa-tags:before { + content: "\f02c"; +} + +.fa-book:before, .icon-book:before { + content: "\f02d"; +} + +.fa-bookmark:before { + content: "\f02e"; +} + +.fa-print:before { + content: "\f02f"; +} + +.fa-camera:before { + content: "\f030"; +} + +.fa-font:before { + content: "\f031"; +} + +.fa-bold:before { + content: "\f032"; +} + +.fa-italic:before { + content: "\f033"; +} + +.fa-text-height:before { + content: "\f034"; +} + +.fa-text-width:before { + content: "\f035"; +} + +.fa-align-left:before { + content: "\f036"; +} + +.fa-align-center:before { + content: "\f037"; +} + +.fa-align-right:before { + content: "\f038"; +} + +.fa-align-justify:before { + content: "\f039"; +} + +.fa-list:before { + content: "\f03a"; +} + +.fa-dedent:before, +.fa-outdent:before { + content: "\f03b"; +} + +.fa-indent:before { + content: "\f03c"; +} + +.fa-video-camera:before { + content: "\f03d"; +} + +.fa-picture-o:before { + content: "\f03e"; +} + +.fa-pencil:before { + content: "\f040"; +} + +.fa-map-marker:before { + content: "\f041"; +} + +.fa-adjust:before { + content: "\f042"; +} + +.fa-tint:before { + content: "\f043"; +} + +.fa-edit:before, +.fa-pencil-square-o:before { + content: "\f044"; +} + +.fa-share-square-o:before { + content: "\f045"; +} + +.fa-check-square-o:before { + content: "\f046"; +} + +.fa-arrows:before { + content: "\f047"; +} + +.fa-step-backward:before { + content: "\f048"; +} + +.fa-fast-backward:before { + content: "\f049"; +} + +.fa-backward:before { + content: "\f04a"; +} + +.fa-play:before { + content: "\f04b"; +} + +.fa-pause:before { + content: "\f04c"; +} + +.fa-stop:before { + content: "\f04d"; +} + +.fa-forward:before { + content: "\f04e"; +} + +.fa-fast-forward:before { + content: "\f050"; +} + +.fa-step-forward:before { + content: "\f051"; +} + +.fa-eject:before { + content: "\f052"; +} + +.fa-chevron-left:before { + content: "\f053"; +} + +.fa-chevron-right:before { + content: "\f054"; +} + +.fa-plus-circle:before { + content: "\f055"; +} + +.fa-minus-circle:before { + content: "\f056"; +} + +.fa-times-circle:before { + content: "\f057"; +} + +.fa-check-circle:before, .wy-inline-validate.wy-inline-validate-success .wy-input-context:before { + content: "\f058"; +} + +.fa-question-circle:before { + content: "\f059"; +} + +.fa-info-circle:before { + content: "\f05a"; +} + +.fa-crosshairs:before { + content: "\f05b"; +} + +.fa-times-circle-o:before, .wy-inline-validate.wy-inline-validate-danger .wy-input-context:before { + content: "\f05c"; +} + +.fa-check-circle-o:before { + content: "\f05d"; +} + +.fa-ban:before { + content: "\f05e"; +} + +.fa-arrow-left:before { + content: "\f060"; +} + +.fa-arrow-right:before { + content: "\f061"; +} + +.fa-arrow-up:before { + content: "\f062"; +} + +.fa-arrow-down:before { + content: "\f063"; +} + +.fa-mail-forward:before, +.fa-share:before { + content: "\f064"; +} + +.fa-expand:before { + content: "\f065"; +} + +.fa-compress:before { + content: "\f066"; +} + +.fa-plus:before { + content: "\f067"; +} + +.fa-minus:before { + content: "\f068"; +} + +.fa-asterisk:before { + content: "\f069"; +} + +.fa-exclamation-circle:before, .wy-inline-validate.wy-inline-validate-warning .wy-input-context:before, .wy-inline-validate.wy-inline-validate-info .wy-input-context:before, .rst-content .admonition-title:before { + content: "\f06a"; +} + +.fa-gift:before { + content: "\f06b"; +} + +.fa-leaf:before { + content: "\f06c"; +} + +.fa-fire:before, .icon-fire:before { + content: "\f06d"; +} + +.fa-eye:before { + content: "\f06e"; +} + +.fa-eye-slash:before { + content: "\f070"; +} + +.fa-warning:before, +.fa-exclamation-triangle:before { + content: "\f071"; +} + +.fa-plane:before { + content: "\f072"; +} + +.fa-calendar:before { + content: "\f073"; +} + +.fa-random:before { + content: "\f074"; +} + +.fa-comment:before { + content: "\f075"; +} + +.fa-magnet:before { + content: "\f076"; +} + +.fa-chevron-up:before { + content: "\f077"; +} + +.fa-chevron-down:before { + content: "\f078"; +} + +.fa-retweet:before { + content: "\f079"; +} + +.fa-shopping-cart:before { + content: "\f07a"; +} + +.fa-folder:before { + content: "\f07b"; +} + +.fa-folder-open:before { + content: "\f07c"; +} + +.fa-arrows-v:before { + content: "\f07d"; +} + +.fa-arrows-h:before { + content: "\f07e"; +} + +.fa-bar-chart-o:before { + content: "\f080"; +} + +.fa-twitter-square:before { + content: "\f081"; +} + +.fa-facebook-square:before { + content: "\f082"; +} + +.fa-camera-retro:before { + content: "\f083"; +} + +.fa-key:before { + content: "\f084"; +} + +.fa-gears:before, +.fa-cogs:before { + content: "\f085"; +} + +.fa-comments:before { + content: "\f086"; +} + +.fa-thumbs-o-up:before { + content: "\f087"; +} + +.fa-thumbs-o-down:before { + content: "\f088"; +} + +.fa-star-half:before { + content: "\f089"; +} + +.fa-heart-o:before { + content: "\f08a"; +} + +.fa-sign-out:before { + content: "\f08b"; +} + +.fa-linkedin-square:before { + content: "\f08c"; +} + +.fa-thumb-tack:before { + content: "\f08d"; +} + +.fa-external-link:before { + content: "\f08e"; +} + +.fa-sign-in:before { + content: "\f090"; +} + +.fa-trophy:before { + content: "\f091"; +} + +.fa-github-square:before { + content: "\f092"; +} + +.fa-upload:before { + content: "\f093"; +} + +.fa-lemon-o:before { + content: "\f094"; +} + +.fa-phone:before { + content: "\f095"; +} + +.fa-square-o:before { + content: "\f096"; +} + +.fa-bookmark-o:before { + content: "\f097"; +} + +.fa-phone-square:before { + content: "\f098"; +} + +.fa-twitter:before { + content: "\f099"; +} + +.fa-facebook:before { + content: "\f09a"; +} + +.fa-github:before, .icon-github:before { + content: "\f09b"; +} + +.fa-unlock:before { + content: "\f09c"; +} + +.fa-credit-card:before { + content: "\f09d"; +} + +.fa-rss:before { + content: "\f09e"; +} + +.fa-hdd-o:before { + content: "\f0a0"; +} + +.fa-bullhorn:before { + content: "\f0a1"; +} + +.fa-bell:before { + content: "\f0f3"; +} + +.fa-certificate:before { + content: "\f0a3"; +} + +.fa-hand-o-right:before { + content: "\f0a4"; +} + +.fa-hand-o-left:before { + content: "\f0a5"; +} + +.fa-hand-o-up:before { + content: "\f0a6"; +} + +.fa-hand-o-down:before { + content: "\f0a7"; +} + +.fa-arrow-circle-left:before, .icon-circle-arrow-left:before { + content: "\f0a8"; +} + +.fa-arrow-circle-right:before, .icon-circle-arrow-right:before { + content: "\f0a9"; +} + +.fa-arrow-circle-up:before { + content: "\f0aa"; +} + +.fa-arrow-circle-down:before { + content: "\f0ab"; +} + +.fa-globe:before { + content: "\f0ac"; +} + +.fa-wrench:before { + content: "\f0ad"; +} + +.fa-tasks:before { + content: "\f0ae"; +} + +.fa-filter:before { + content: "\f0b0"; +} + +.fa-briefcase:before { + content: "\f0b1"; +} + +.fa-arrows-alt:before { + content: "\f0b2"; +} + +.fa-group:before, +.fa-users:before { + content: "\f0c0"; +} + +.fa-chain:before, +.fa-link:before, +.icon-link:before { + content: "\f0c1"; +} + +.fa-cloud:before { + content: "\f0c2"; +} + +.fa-flask:before { + content: "\f0c3"; +} + +.fa-cut:before, +.fa-scissors:before { + content: "\f0c4"; +} + +.fa-copy:before, +.fa-files-o:before { + content: "\f0c5"; +} + +.fa-paperclip:before { + content: "\f0c6"; +} + +.fa-save:before, +.fa-floppy-o:before { + content: "\f0c7"; +} + +.fa-square:before { + content: "\f0c8"; +} + +.fa-bars:before { + content: "\f0c9"; +} + +.fa-list-ul:before { + content: "\f0ca"; +} + +.fa-list-ol:before { + content: "\f0cb"; +} + +.fa-strikethrough:before { + content: "\f0cc"; +} + +.fa-underline:before { + content: "\f0cd"; +} + +.fa-table:before { + content: "\f0ce"; +} + +.fa-magic:before { + content: "\f0d0"; +} + +.fa-truck:before { + content: "\f0d1"; +} + +.fa-pinterest:before { + content: "\f0d2"; +} + +.fa-pinterest-square:before { + content: "\f0d3"; +} + +.fa-google-plus-square:before { + content: "\f0d4"; +} + +.fa-google-plus:before { + content: "\f0d5"; +} + +.fa-money:before { + content: "\f0d6"; +} + +.fa-caret-down:before, .wy-dropdown .caret:before, .icon-caret-down:before { + content: "\f0d7"; +} + +.fa-caret-up:before { + content: "\f0d8"; +} + +.fa-caret-left:before { + content: "\f0d9"; +} + +.fa-caret-right:before { + content: "\f0da"; +} + +.fa-columns:before { + content: "\f0db"; +} + +.fa-unsorted:before, +.fa-sort:before { + content: "\f0dc"; +} + +.fa-sort-down:before, +.fa-sort-asc:before { + content: "\f0dd"; +} + +.fa-sort-up:before, +.fa-sort-desc:before { + content: "\f0de"; +} + +.fa-envelope:before { + content: "\f0e0"; +} + +.fa-linkedin:before { + content: "\f0e1"; +} + +.fa-rotate-left:before, +.fa-undo:before { + content: "\f0e2"; +} + +.fa-legal:before, +.fa-gavel:before { + content: "\f0e3"; +} + +.fa-dashboard:before, +.fa-tachometer:before { + content: "\f0e4"; +} + +.fa-comment-o:before { + content: "\f0e5"; +} + +.fa-comments-o:before { + content: "\f0e6"; +} + +.fa-flash:before, +.fa-bolt:before { + content: "\f0e7"; +} + +.fa-sitemap:before { + content: "\f0e8"; +} + +.fa-umbrella:before { + content: "\f0e9"; +} + +.fa-paste:before, +.fa-clipboard:before { + content: "\f0ea"; +} + +.fa-lightbulb-o:before { + content: "\f0eb"; +} + +.fa-exchange:before { + content: "\f0ec"; +} + +.fa-cloud-download:before { + content: "\f0ed"; +} + +.fa-cloud-upload:before { + content: "\f0ee"; +} + +.fa-user-md:before { + content: "\f0f0"; +} + +.fa-stethoscope:before { + content: "\f0f1"; +} + +.fa-suitcase:before { + content: "\f0f2"; +} + +.fa-bell-o:before { + content: "\f0a2"; +} + +.fa-coffee:before { + content: "\f0f4"; +} + +.fa-cutlery:before { + content: "\f0f5"; +} + +.fa-file-text-o:before { + content: "\f0f6"; +} + +.fa-building-o:before { + content: "\f0f7"; +} + +.fa-hospital-o:before { + content: "\f0f8"; +} + +.fa-ambulance:before { + content: "\f0f9"; +} + +.fa-medkit:before { + content: "\f0fa"; +} + +.fa-fighter-jet:before { + content: "\f0fb"; +} + +.fa-beer:before { + content: "\f0fc"; +} + +.fa-h-square:before { + content: "\f0fd"; +} + +.fa-plus-square:before { + content: "\f0fe"; +} + +.fa-angle-double-left:before { + content: "\f100"; +} + +.fa-angle-double-right:before { + content: "\f101"; +} + +.fa-angle-double-up:before { + content: "\f102"; +} + +.fa-angle-double-down:before { + content: "\f103"; +} + +.fa-angle-left:before { + content: "\f104"; +} + +.fa-angle-right:before { + content: "\f105"; +} + +.fa-angle-up:before { + content: "\f106"; +} + +.fa-angle-down:before { + content: "\f107"; +} + +.fa-desktop:before { + content: "\f108"; +} + +.fa-laptop:before { + content: "\f109"; +} + +.fa-tablet:before { + content: "\f10a"; +} + +.fa-mobile-phone:before, +.fa-mobile:before { + content: "\f10b"; +} + +.fa-circle-o:before { + content: "\f10c"; +} + +.fa-quote-left:before { + content: "\f10d"; +} + +.fa-quote-right:before { + content: "\f10e"; +} + +.fa-spinner:before { + content: "\f110"; +} + +.fa-circle:before { + content: "\f111"; +} + +.fa-mail-reply:before, +.fa-reply:before { + content: "\f112"; +} + +.fa-github-alt:before { + content: "\f113"; +} + +.fa-folder-o:before { + content: "\f114"; +} + +.fa-folder-open-o:before { + content: "\f115"; +} + +.fa-smile-o:before { + content: "\f118"; +} + +.fa-frown-o:before { + content: "\f119"; +} + +.fa-meh-o:before { + content: "\f11a"; +} + +.fa-gamepad:before { + content: "\f11b"; +} + +.fa-keyboard-o:before { + content: "\f11c"; +} + +.fa-flag-o:before { + content: "\f11d"; +} + +.fa-flag-checkered:before { + content: "\f11e"; +} + +.fa-terminal:before { + content: "\f120"; +} + +.fa-code:before { + content: "\f121"; +} + +.fa-reply-all:before { + content: "\f122"; +} + +.fa-mail-reply-all:before { + content: "\f122"; +} + +.fa-star-half-empty:before, +.fa-star-half-full:before, +.fa-star-half-o:before { + content: "\f123"; +} + +.fa-location-arrow:before { + content: "\f124"; +} + +.fa-crop:before { + content: "\f125"; +} + +.fa-code-fork:before { + content: "\f126"; +} + +.fa-unlink:before, +.fa-chain-broken:before { + content: "\f127"; +} + +.fa-question:before { + content: "\f128"; +} + +.fa-info:before { + content: "\f129"; +} + +.fa-exclamation:before { + content: "\f12a"; +} + +.fa-superscript:before { + content: "\f12b"; +} + +.fa-subscript:before { + content: "\f12c"; +} + +.fa-eraser:before { + content: "\f12d"; +} + +.fa-puzzle-piece:before { + content: "\f12e"; +} + +.fa-microphone:before { + content: "\f130"; +} + +.fa-microphone-slash:before { + content: "\f131"; +} + +.fa-shield:before { + content: "\f132"; +} + +.fa-calendar-o:before { + content: "\f133"; +} + +.fa-fire-extinguisher:before { + content: "\f134"; +} + +.fa-rocket:before { + content: "\f135"; +} + +.fa-maxcdn:before { + content: "\f136"; +} + +.fa-chevron-circle-left:before { + content: "\f137"; +} + +.fa-chevron-circle-right:before { + content: "\f138"; +} + +.fa-chevron-circle-up:before { + content: "\f139"; +} + +.fa-chevron-circle-down:before { + content: "\f13a"; +} + +.fa-html5:before { + content: "\f13b"; +} + +.fa-css3:before { + content: "\f13c"; +} + +.fa-anchor:before { + content: "\f13d"; +} + +.fa-unlock-alt:before { + content: "\f13e"; +} + +.fa-bullseye:before { + content: "\f140"; +} + +.fa-ellipsis-h:before { + content: "\f141"; +} + +.fa-ellipsis-v:before { + content: "\f142"; +} + +.fa-rss-square:before { + content: "\f143"; +} + +.fa-play-circle:before { + content: "\f144"; +} + +.fa-ticket:before { + content: "\f145"; +} + +.fa-minus-square:before { + content: "\f146"; +} + +.fa-minus-square-o:before { + content: "\f147"; +} + +.fa-level-up:before { + content: "\f148"; +} + +.fa-level-down:before { + content: "\f149"; +} + +.fa-check-square:before { + content: "\f14a"; +} + +.fa-pencil-square:before { + content: "\f14b"; +} + +.fa-external-link-square:before { + content: "\f14c"; +} + +.fa-share-square:before { + content: "\f14d"; +} + +.fa-compass:before { + content: "\f14e"; +} + +.fa-toggle-down:before, +.fa-caret-square-o-down:before { + content: "\f150"; +} + +.fa-toggle-up:before, +.fa-caret-square-o-up:before { + content: "\f151"; +} + +.fa-toggle-right:before, +.fa-caret-square-o-right:before { + content: "\f152"; +} + +.fa-euro:before, +.fa-eur:before { + content: "\f153"; +} + +.fa-gbp:before { + content: "\f154"; +} + +.fa-dollar:before, +.fa-usd:before { + content: "\f155"; +} + +.fa-rupee:before, +.fa-inr:before { + content: "\f156"; +} + +.fa-cny:before, +.fa-rmb:before, +.fa-yen:before, +.fa-jpy:before { + content: "\f157"; +} + +.fa-ruble:before, +.fa-rouble:before, +.fa-rub:before { + content: "\f158"; +} + +.fa-won:before, +.fa-krw:before { + content: "\f159"; +} + +.fa-bitcoin:before, +.fa-btc:before { + content: "\f15a"; +} + +.fa-file:before { + content: "\f15b"; +} + +.fa-file-text:before { + content: "\f15c"; +} + +.fa-sort-alpha-asc:before { + content: "\f15d"; +} + +.fa-sort-alpha-desc:before { + content: "\f15e"; +} + +.fa-sort-amount-asc:before { + content: "\f160"; +} + +.fa-sort-amount-desc:before { + content: "\f161"; +} + +.fa-sort-numeric-asc:before { + content: "\f162"; +} + +.fa-sort-numeric-desc:before { + content: "\f163"; +} + +.fa-thumbs-up:before { + content: "\f164"; +} + +.fa-thumbs-down:before { + content: "\f165"; +} + +.fa-youtube-square:before { + content: "\f166"; +} + +.fa-youtube:before { + content: "\f167"; +} + +.fa-xing:before { + content: "\f168"; +} + +.fa-xing-square:before { + content: "\f169"; +} + +.fa-youtube-play:before { + content: "\f16a"; +} + +.fa-dropbox:before { + content: "\f16b"; +} + +.fa-stack-overflow:before { + content: "\f16c"; +} + +.fa-instagram:before { + content: "\f16d"; +} + +.fa-flickr:before { + content: "\f16e"; +} + +.fa-adn:before { + content: "\f170"; +} + +.fa-bitbucket:before, .icon-bitbucket:before { + content: "\f171"; +} + +.fa-bitbucket-square:before { + content: "\f172"; +} + +.fa-tumblr:before { + content: "\f173"; +} + +.fa-tumblr-square:before { + content: "\f174"; +} + +.fa-long-arrow-down:before { + content: "\f175"; +} + +.fa-long-arrow-up:before { + content: "\f176"; +} + +.fa-long-arrow-left:before { + content: "\f177"; +} + +.fa-long-arrow-right:before { + content: "\f178"; +} + +.fa-apple:before { + content: "\f179"; +} + +.fa-windows:before { + content: "\f17a"; +} + +.fa-android:before { + content: "\f17b"; +} + +.fa-linux:before { + content: "\f17c"; +} + +.fa-dribbble:before { + content: "\f17d"; +} + +.fa-skype:before { + content: "\f17e"; +} + +.fa-foursquare:before { + content: "\f180"; +} + +.fa-trello:before { + content: "\f181"; +} + +.fa-female:before { + content: "\f182"; +} + +.fa-male:before { + content: "\f183"; +} + +.fa-gittip:before { + content: "\f184"; +} + +.fa-sun-o:before { + content: "\f185"; +} + +.fa-moon-o:before { + content: "\f186"; +} + +.fa-archive:before { + content: "\f187"; +} + +.fa-bug:before { + content: "\f188"; +} + +.fa-vk:before { + content: "\f189"; +} + +.fa-weibo:before { + content: "\f18a"; +} + +.fa-renren:before { + content: "\f18b"; +} + +.fa-pagelines:before { + content: "\f18c"; +} + +.fa-stack-exchange:before { + content: "\f18d"; +} + +.fa-arrow-circle-o-right:before { + content: "\f18e"; +} + +.fa-arrow-circle-o-left:before { + content: "\f190"; +} + +.fa-toggle-left:before, +.fa-caret-square-o-left:before { + content: "\f191"; +} + +.fa-dot-circle-o:before { + content: "\f192"; +} + +.fa-wheelchair:before { + content: "\f193"; +} + +.fa-vimeo-square:before { + content: "\f194"; +} + +.fa-turkish-lira:before, +.fa-try:before { + content: "\f195"; +} + +.fa-plus-square-o:before { + content: "\f196"; +} + +.btn .fa, .btn .wy-dropdown .caret, .wy-dropdown .btn .caret, .btn .wy-inline-validate.wy-inline-validate-success .wy-input-context, .wy-inline-validate.wy-inline-validate-success .btn .wy-input-context, .btn .wy-inline-validate.wy-inline-validate-danger .wy-input-context, .wy-inline-validate.wy-inline-validate-danger .btn .wy-input-context, .btn .wy-inline-validate.wy-inline-validate-warning .wy-input-context, .wy-inline-validate.wy-inline-validate-warning .btn .wy-input-context, .btn .wy-inline-validate.wy-inline-validate-info .wy-input-context, .wy-inline-validate.wy-inline-validate-info .btn .wy-input-context, .btn .wy-tag-input-group .wy-tag .wy-tag-remove, .wy-tag-input-group .wy-tag .btn .wy-tag-remove, .btn .rst-content .admonition-title, .rst-content .btn .admonition-title, .btn .rst-content h1 .headerlink, .rst-content h1 .btn .headerlink, .btn .rst-content h2 .headerlink, .rst-content h2 .btn .headerlink, .btn .rst-content h3 .headerlink, .rst-content h3 .btn .headerlink, .btn .rst-content h4 .headerlink, .rst-content h4 .btn .headerlink, .btn .rst-content h5 .headerlink, .rst-content h5 .btn .headerlink, .btn .rst-content h6 .headerlink, .rst-content h6 .btn .headerlink, .btn .rst-content dl dt .headerlink, .rst-content dl dt .btn .headerlink, .btn .icon, .nav .fa, .nav .wy-dropdown .caret, .wy-dropdown .nav .caret, .nav .wy-inline-validate.wy-inline-validate-success .wy-input-context, .wy-inline-validate.wy-inline-validate-success .nav .wy-input-context, .nav .wy-inline-validate.wy-inline-validate-danger .wy-input-context, .wy-inline-validate.wy-inline-validate-danger .nav .wy-input-context, .nav .wy-inline-validate.wy-inline-validate-warning .wy-input-context, .wy-inline-validate.wy-inline-validate-warning .nav .wy-input-context, .nav .wy-inline-validate.wy-inline-validate-info .wy-input-context, .wy-inline-validate.wy-inline-validate-info .nav .wy-input-context, .nav .wy-tag-input-group .wy-tag .wy-tag-remove, .wy-tag-input-group .wy-tag .nav .wy-tag-remove, .nav .rst-content .admonition-title, .rst-content .nav .admonition-title, .nav .rst-content h1 .headerlink, .rst-content h1 .nav .headerlink, .nav .rst-content h2 .headerlink, .rst-content h2 .nav .headerlink, .nav .rst-content h3 .headerlink, .rst-content h3 .nav .headerlink, .nav .rst-content h4 .headerlink, .rst-content h4 .nav .headerlink, .nav .rst-content h5 .headerlink, .rst-content h5 .nav .headerlink, .nav .rst-content h6 .headerlink, .rst-content h6 .nav .headerlink, .nav .rst-content dl dt .headerlink, .rst-content dl dt .nav .headerlink, .nav .icon { + display: inline; +} +.btn .fa.fa-large, .btn .wy-dropdown .fa-large.caret, .wy-dropdown .btn .fa-large.caret, .btn .wy-inline-validate.wy-inline-validate-success .fa-large.wy-input-context, .wy-inline-validate.wy-inline-validate-success .btn .fa-large.wy-input-context, .btn .wy-inline-validate.wy-inline-validate-danger .fa-large.wy-input-context, .wy-inline-validate.wy-inline-validate-danger .btn .fa-large.wy-input-context, .btn .wy-inline-validate.wy-inline-validate-warning .fa-large.wy-input-context, .wy-inline-validate.wy-inline-validate-warning .btn .fa-large.wy-input-context, .btn .wy-inline-validate.wy-inline-validate-info .fa-large.wy-input-context, .wy-inline-validate.wy-inline-validate-info .btn .fa-large.wy-input-context, .btn .wy-tag-input-group .wy-tag .fa-large.wy-tag-remove, .wy-tag-input-group .wy-tag .btn .fa-large.wy-tag-remove, .btn .rst-content .fa-large.admonition-title, .rst-content .btn .fa-large.admonition-title, .btn .rst-content h1 .fa-large.headerlink, .rst-content h1 .btn .fa-large.headerlink, .btn .rst-content h2 .fa-large.headerlink, .rst-content h2 .btn .fa-large.headerlink, .btn .rst-content h3 .fa-large.headerlink, .rst-content h3 .btn .fa-large.headerlink, .btn .rst-content h4 .fa-large.headerlink, .rst-content h4 .btn .fa-large.headerlink, .btn .rst-content h5 .fa-large.headerlink, .rst-content h5 .btn .fa-large.headerlink, .btn .rst-content h6 .fa-large.headerlink, .rst-content h6 .btn .fa-large.headerlink, .btn .rst-content dl dt .fa-large.headerlink, .rst-content dl dt .btn .fa-large.headerlink, .btn .fa-large.icon, .nav .fa.fa-large, .nav .wy-dropdown .fa-large.caret, .wy-dropdown .nav .fa-large.caret, .nav .wy-inline-validate.wy-inline-validate-success .fa-large.wy-input-context, .wy-inline-validate.wy-inline-validate-success .nav .fa-large.wy-input-context, .nav .wy-inline-validate.wy-inline-validate-danger .fa-large.wy-input-context, .wy-inline-validate.wy-inline-validate-danger .nav .fa-large.wy-input-context, .nav .wy-inline-validate.wy-inline-validate-warning .fa-large.wy-input-context, .wy-inline-validate.wy-inline-validate-warning .nav .fa-large.wy-input-context, .nav .wy-inline-validate.wy-inline-validate-info .fa-large.wy-input-context, .wy-inline-validate.wy-inline-validate-info .nav .fa-large.wy-input-context, .nav .wy-tag-input-group .wy-tag .fa-large.wy-tag-remove, .wy-tag-input-group .wy-tag .nav .fa-large.wy-tag-remove, .nav .rst-content .fa-large.admonition-title, .rst-content .nav .fa-large.admonition-title, .nav .rst-content h1 .fa-large.headerlink, .rst-content h1 .nav .fa-large.headerlink, .nav .rst-content h2 .fa-large.headerlink, .rst-content h2 .nav .fa-large.headerlink, .nav .rst-content h3 .fa-large.headerlink, .rst-content h3 .nav .fa-large.headerlink, .nav .rst-content h4 .fa-large.headerlink, .rst-content h4 .nav .fa-large.headerlink, .nav .rst-content h5 .fa-large.headerlink, .rst-content h5 .nav .fa-large.headerlink, .nav .rst-content h6 .fa-large.headerlink, .rst-content h6 .nav .fa-large.headerlink, .nav .rst-content dl dt .fa-large.headerlink, .rst-content dl dt .nav .fa-large.headerlink, .nav .fa-large.icon { + line-height: 0.9em; +} +.btn .fa.fa-spin, .btn .wy-dropdown .fa-spin.caret, .wy-dropdown .btn .fa-spin.caret, .btn .wy-inline-validate.wy-inline-validate-success .fa-spin.wy-input-context, .wy-inline-validate.wy-inline-validate-success .btn .fa-spin.wy-input-context, .btn .wy-inline-validate.wy-inline-validate-danger .fa-spin.wy-input-context, .wy-inline-validate.wy-inline-validate-danger .btn .fa-spin.wy-input-context, .btn .wy-inline-validate.wy-inline-validate-warning .fa-spin.wy-input-context, .wy-inline-validate.wy-inline-validate-warning .btn .fa-spin.wy-input-context, .btn .wy-inline-validate.wy-inline-validate-info .fa-spin.wy-input-context, .wy-inline-validate.wy-inline-validate-info .btn .fa-spin.wy-input-context, .btn .wy-tag-input-group .wy-tag .fa-spin.wy-tag-remove, .wy-tag-input-group .wy-tag .btn .fa-spin.wy-tag-remove, .btn .rst-content .fa-spin.admonition-title, .rst-content .btn .fa-spin.admonition-title, .btn .rst-content h1 .fa-spin.headerlink, .rst-content h1 .btn .fa-spin.headerlink, .btn .rst-content h2 .fa-spin.headerlink, .rst-content h2 .btn .fa-spin.headerlink, .btn .rst-content h3 .fa-spin.headerlink, .rst-content h3 .btn .fa-spin.headerlink, .btn .rst-content h4 .fa-spin.headerlink, .rst-content h4 .btn .fa-spin.headerlink, .btn .rst-content h5 .fa-spin.headerlink, .rst-content h5 .btn .fa-spin.headerlink, .btn .rst-content h6 .fa-spin.headerlink, .rst-content h6 .btn .fa-spin.headerlink, .btn .rst-content dl dt .fa-spin.headerlink, .rst-content dl dt .btn .fa-spin.headerlink, .btn .fa-spin.icon, .nav .fa.fa-spin, .nav .wy-dropdown .fa-spin.caret, .wy-dropdown .nav .fa-spin.caret, .nav .wy-inline-validate.wy-inline-validate-success .fa-spin.wy-input-context, .wy-inline-validate.wy-inline-validate-success .nav .fa-spin.wy-input-context, .nav .wy-inline-validate.wy-inline-validate-danger .fa-spin.wy-input-context, .wy-inline-validate.wy-inline-validate-danger .nav .fa-spin.wy-input-context, .nav .wy-inline-validate.wy-inline-validate-warning .fa-spin.wy-input-context, .wy-inline-validate.wy-inline-validate-warning .nav .fa-spin.wy-input-context, .nav .wy-inline-validate.wy-inline-validate-info .fa-spin.wy-input-context, .wy-inline-validate.wy-inline-validate-info .nav .fa-spin.wy-input-context, .nav .wy-tag-input-group .wy-tag .fa-spin.wy-tag-remove, .wy-tag-input-group .wy-tag .nav .fa-spin.wy-tag-remove, .nav .rst-content .fa-spin.admonition-title, .rst-content .nav .fa-spin.admonition-title, .nav .rst-content h1 .fa-spin.headerlink, .rst-content h1 .nav .fa-spin.headerlink, .nav .rst-content h2 .fa-spin.headerlink, .rst-content h2 .nav .fa-spin.headerlink, .nav .rst-content h3 .fa-spin.headerlink, .rst-content h3 .nav .fa-spin.headerlink, .nav .rst-content h4 .fa-spin.headerlink, .rst-content h4 .nav .fa-spin.headerlink, .nav .rst-content h5 .fa-spin.headerlink, .rst-content h5 .nav .fa-spin.headerlink, .nav .rst-content h6 .fa-spin.headerlink, .rst-content h6 .nav .fa-spin.headerlink, .nav .rst-content dl dt .fa-spin.headerlink, .rst-content dl dt .nav .fa-spin.headerlink, .nav .fa-spin.icon { + display: inline-block; +} + +.btn.fa:before, .wy-dropdown .btn.caret:before, .wy-inline-validate.wy-inline-validate-success .btn.wy-input-context:before, .wy-inline-validate.wy-inline-validate-danger .btn.wy-input-context:before, .wy-inline-validate.wy-inline-validate-warning .btn.wy-input-context:before, .wy-inline-validate.wy-inline-validate-info .btn.wy-input-context:before, .wy-tag-input-group .wy-tag .btn.wy-tag-remove:before, .rst-content .btn.admonition-title:before, .rst-content h1 .btn.headerlink:before, .rst-content h2 .btn.headerlink:before, .rst-content h3 .btn.headerlink:before, .rst-content h4 .btn.headerlink:before, .rst-content h5 .btn.headerlink:before, .rst-content h6 .btn.headerlink:before, .rst-content dl dt .btn.headerlink:before, .btn.icon:before { + opacity: 0.5; + -webkit-transition: opacity 0.05s ease-in; + -moz-transition: opacity 0.05s ease-in; + transition: opacity 0.05s ease-in; +} + +.btn.fa:hover:before, .wy-dropdown .btn.caret:hover:before, .wy-inline-validate.wy-inline-validate-success .btn.wy-input-context:hover:before, .wy-inline-validate.wy-inline-validate-danger .btn.wy-input-context:hover:before, .wy-inline-validate.wy-inline-validate-warning .btn.wy-input-context:hover:before, .wy-inline-validate.wy-inline-validate-info .btn.wy-input-context:hover:before, .wy-tag-input-group .wy-tag .btn.wy-tag-remove:hover:before, .rst-content .btn.admonition-title:hover:before, .rst-content h1 .btn.headerlink:hover:before, .rst-content h2 .btn.headerlink:hover:before, .rst-content h3 .btn.headerlink:hover:before, .rst-content h4 .btn.headerlink:hover:before, .rst-content h5 .btn.headerlink:hover:before, .rst-content h6 .btn.headerlink:hover:before, .rst-content dl dt .btn.headerlink:hover:before, .btn.icon:hover:before { + opacity: 1; +} + +.btn-mini .fa:before, .btn-mini .wy-dropdown .caret:before, .wy-dropdown .btn-mini .caret:before, .btn-mini .wy-inline-validate.wy-inline-validate-success .wy-input-context:before, .wy-inline-validate.wy-inline-validate-success .btn-mini .wy-input-context:before, .btn-mini .wy-inline-validate.wy-inline-validate-danger .wy-input-context:before, .wy-inline-validate.wy-inline-validate-danger .btn-mini .wy-input-context:before, .btn-mini .wy-inline-validate.wy-inline-validate-warning .wy-input-context:before, .wy-inline-validate.wy-inline-validate-warning .btn-mini .wy-input-context:before, .btn-mini .wy-inline-validate.wy-inline-validate-info .wy-input-context:before, .wy-inline-validate.wy-inline-validate-info .btn-mini .wy-input-context:before, .btn-mini .wy-tag-input-group .wy-tag .wy-tag-remove:before, .wy-tag-input-group .wy-tag .btn-mini .wy-tag-remove:before, .btn-mini .rst-content .admonition-title:before, .rst-content .btn-mini .admonition-title:before, .btn-mini .rst-content h1 .headerlink:before, .rst-content h1 .btn-mini .headerlink:before, .btn-mini .rst-content h2 .headerlink:before, .rst-content h2 .btn-mini .headerlink:before, .btn-mini .rst-content h3 .headerlink:before, .rst-content h3 .btn-mini .headerlink:before, .btn-mini .rst-content h4 .headerlink:before, .rst-content h4 .btn-mini .headerlink:before, .btn-mini .rst-content h5 .headerlink:before, .rst-content h5 .btn-mini .headerlink:before, .btn-mini .rst-content h6 .headerlink:before, .rst-content h6 .btn-mini .headerlink:before, .btn-mini .rst-content dl dt .headerlink:before, .rst-content dl dt .btn-mini .headerlink:before, .btn-mini .icon:before { + font-size: 14px; + vertical-align: -15%; +} + +.wy-alert, .rst-content .note, .rst-content .attention, .rst-content .caution, .rst-content .danger, .rst-content .error, .rst-content .hint, .rst-content .important, .rst-content .tip, .rst-content .warning, .rst-content .seealso { + padding: 12px; + line-height: 24px; + margin-bottom: 24px; +} + +.wy-alert-title, .rst-content .admonition-title { + color: white; + font-weight: bold; + display: block; + color: white; + background: transparent; + margin: -12px; + padding: 6px 12px; + margin-bottom: 12px; +} + +.wy-alert.wy-alert-danger, .rst-content .wy-alert-danger.note, .rst-content .wy-alert-danger.attention, .rst-content .wy-alert-danger.caution, .rst-content .danger, .rst-content .error, .rst-content .wy-alert-danger.hint, .rst-content .wy-alert-danger.important, .rst-content .wy-alert-danger.tip, .rst-content .wy-alert-danger.warning, .rst-content .wy-alert-danger.seealso { + background: #fdf3f2; +} +.wy-alert.wy-alert-danger .wy-alert-title, .rst-content .wy-alert-danger.note .wy-alert-title, .rst-content .wy-alert-danger.attention .wy-alert-title, .rst-content .wy-alert-danger.caution .wy-alert-title, .rst-content .danger .wy-alert-title, .rst-content .error .wy-alert-title, .rst-content .wy-alert-danger.hint .wy-alert-title, .rst-content .wy-alert-danger.important .wy-alert-title, .rst-content .wy-alert-danger.tip .wy-alert-title, .rst-content .wy-alert-danger.warning .wy-alert-title, .rst-content .wy-alert-danger.seealso .wy-alert-title, .wy-alert.wy-alert-danger .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-danger .admonition-title, .rst-content .wy-alert-danger.note .admonition-title, .rst-content .wy-alert-danger.attention .admonition-title, .rst-content .wy-alert-danger.caution .admonition-title, .rst-content .danger .admonition-title, .rst-content .error .admonition-title, .rst-content .wy-alert-danger.hint .admonition-title, .rst-content .wy-alert-danger.important .admonition-title, .rst-content .wy-alert-danger.tip .admonition-title, .rst-content .wy-alert-danger.warning .admonition-title, .rst-content .wy-alert-danger.seealso .admonition-title { + background: #f29f97; +} + +.wy-alert.wy-alert-warning, .rst-content .wy-alert-warning.note, .rst-content .attention, .rst-content .caution, .rst-content .wy-alert-warning.danger, .rst-content .wy-alert-warning.error, .rst-content .wy-alert-warning.hint, .rst-content .wy-alert-warning.important, .rst-content .wy-alert-warning.tip, .rst-content .warning, .rst-content .wy-alert-warning.seealso { + background: #ffedcc; +} +.wy-alert.wy-alert-warning .wy-alert-title, .rst-content .wy-alert-warning.note .wy-alert-title, .rst-content .attention .wy-alert-title, .rst-content .caution .wy-alert-title, .rst-content .wy-alert-warning.danger .wy-alert-title, .rst-content .wy-alert-warning.error .wy-alert-title, .rst-content .wy-alert-warning.hint .wy-alert-title, .rst-content .wy-alert-warning.important .wy-alert-title, .rst-content .wy-alert-warning.tip .wy-alert-title, .rst-content .warning .wy-alert-title, .rst-content .wy-alert-warning.seealso .wy-alert-title, .wy-alert.wy-alert-warning .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-warning .admonition-title, .rst-content .wy-alert-warning.note .admonition-title, .rst-content .attention .admonition-title, .rst-content .caution .admonition-title, .rst-content .wy-alert-warning.danger .admonition-title, .rst-content .wy-alert-warning.error .admonition-title, .rst-content .wy-alert-warning.hint .admonition-title, .rst-content .wy-alert-warning.important .admonition-title, .rst-content .wy-alert-warning.tip .admonition-title, .rst-content .warning .admonition-title, .rst-content .wy-alert-warning.seealso .admonition-title { + background: #f0b37e; +} + +.wy-alert.wy-alert-info, .rst-content .note, .rst-content .wy-alert-info.attention, .rst-content .wy-alert-info.caution, .rst-content .wy-alert-info.danger, .rst-content .wy-alert-info.error, .rst-content .wy-alert-info.hint, .rst-content .wy-alert-info.important, .rst-content .wy-alert-info.tip, .rst-content .wy-alert-info.warning, .rst-content .seealso { + background: #e7f2fa; +} +.wy-alert.wy-alert-info .wy-alert-title, .rst-content .note .wy-alert-title, .rst-content .wy-alert-info.attention .wy-alert-title, .rst-content .wy-alert-info.caution .wy-alert-title, .rst-content .wy-alert-info.danger .wy-alert-title, .rst-content .wy-alert-info.error .wy-alert-title, .rst-content .wy-alert-info.hint .wy-alert-title, .rst-content .wy-alert-info.important .wy-alert-title, .rst-content .wy-alert-info.tip .wy-alert-title, .rst-content .wy-alert-info.warning .wy-alert-title, .rst-content .seealso .wy-alert-title, .wy-alert.wy-alert-info .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-info .admonition-title, .rst-content .note .admonition-title, .rst-content .wy-alert-info.attention .admonition-title, .rst-content .wy-alert-info.caution .admonition-title, .rst-content .wy-alert-info.danger .admonition-title, .rst-content .wy-alert-info.error .admonition-title, .rst-content .wy-alert-info.hint .admonition-title, .rst-content .wy-alert-info.important .admonition-title, .rst-content .wy-alert-info.tip .admonition-title, .rst-content .wy-alert-info.warning .admonition-title, .rst-content .seealso .admonition-title { + background: #6ab0de; +} + +.wy-alert.wy-alert-success, .rst-content .wy-alert-success.note, .rst-content .wy-alert-success.attention, .rst-content .wy-alert-success.caution, .rst-content .wy-alert-success.danger, .rst-content .wy-alert-success.error, .rst-content .hint, .rst-content .important, .rst-content .tip, .rst-content .wy-alert-success.warning, .rst-content .wy-alert-success.seealso { + background: #dbfaf4; +} +.wy-alert.wy-alert-success .wy-alert-title, .rst-content .wy-alert-success.note .wy-alert-title, .rst-content .wy-alert-success.attention .wy-alert-title, .rst-content .wy-alert-success.caution .wy-alert-title, .rst-content .wy-alert-success.danger .wy-alert-title, .rst-content .wy-alert-success.error .wy-alert-title, .rst-content .hint .wy-alert-title, .rst-content .important .wy-alert-title, .rst-content .tip .wy-alert-title, .rst-content .wy-alert-success.warning .wy-alert-title, .rst-content .wy-alert-success.seealso .wy-alert-title, .wy-alert.wy-alert-success .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-success .admonition-title, .rst-content .wy-alert-success.note .admonition-title, .rst-content .wy-alert-success.attention .admonition-title, .rst-content .wy-alert-success.caution .admonition-title, .rst-content .wy-alert-success.danger .admonition-title, .rst-content .wy-alert-success.error .admonition-title, .rst-content .hint .admonition-title, .rst-content .important .admonition-title, .rst-content .tip .admonition-title, .rst-content .wy-alert-success.warning .admonition-title, .rst-content .wy-alert-success.seealso .admonition-title { + background: #1abc9c; +} + +.wy-alert.wy-alert-neutral, .rst-content .wy-alert-neutral.note, .rst-content .wy-alert-neutral.attention, .rst-content .wy-alert-neutral.caution, .rst-content .wy-alert-neutral.danger, .rst-content .wy-alert-neutral.error, .rst-content .wy-alert-neutral.hint, .rst-content .wy-alert-neutral.important, .rst-content .wy-alert-neutral.tip, .rst-content .wy-alert-neutral.warning, .rst-content .wy-alert-neutral.seealso { + background: #f3f6f6; +} +.wy-alert.wy-alert-neutral strong, .rst-content .wy-alert-neutral.note strong, .rst-content .wy-alert-neutral.attention strong, .rst-content .wy-alert-neutral.caution strong, .rst-content .wy-alert-neutral.danger strong, .rst-content .wy-alert-neutral.error strong, .rst-content .wy-alert-neutral.hint strong, .rst-content .wy-alert-neutral.important strong, .rst-content .wy-alert-neutral.tip strong, .rst-content .wy-alert-neutral.warning strong, .rst-content .wy-alert-neutral.seealso strong { + color: #404040; +} +.wy-alert.wy-alert-neutral a, .rst-content .wy-alert-neutral.note a, .rst-content .wy-alert-neutral.attention a, .rst-content .wy-alert-neutral.caution a, .rst-content .wy-alert-neutral.danger a, .rst-content .wy-alert-neutral.error a, .rst-content .wy-alert-neutral.hint a, .rst-content .wy-alert-neutral.important a, .rst-content .wy-alert-neutral.tip a, .rst-content .wy-alert-neutral.warning a, .rst-content .wy-alert-neutral.seealso a { + color: #2980b9; +} + +.wy-tray-container { + position: fixed; + top: -50px; + left: 0; + width: 100%; + -webkit-transition: top 0.2s ease-in; + -moz-transition: top 0.2s ease-in; + transition: top 0.2s ease-in; +} +.wy-tray-container.on { + top: 0; +} +.wy-tray-container li { + display: none; + width: 100%; + background: #343131; + padding: 12px 24px; + color: white; + margin-bottom: 6px; + text-align: center; + box-shadow: 0 5px 5px 0 rgba(0, 0, 0, 0.1), 0px -1px 2px -1px rgba(255, 255, 255, 0.5) inset; +} +.wy-tray-container li.wy-tray-item-success { + background: #27ae60; +} +.wy-tray-container li.wy-tray-item-info { + background: #2980b9; +} +.wy-tray-container li.wy-tray-item-warning { + background: #e67e22; +} +.wy-tray-container li.wy-tray-item-danger { + background: #e74c3c; +} + +.btn { + /* Structure */ + display: inline-block; + *display: inline; + /*IE 6/7 */ + zoom: 1; + line-height: normal; + white-space: nowrap; + vertical-align: baseline; + text-align: center; + cursor: pointer; + -webkit-user-drag: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + font-size: 100%; + padding: 6px 12px; + color: white; + border: 1px solid rgba(0, 0, 0, 0.1); + border-bottom: solid 3px rgba(0, 0, 0, 0.1); + background-color: #27ae60; + text-decoration: none; + font-weight: 500; + box-shadow: 0px 1px 2px -1px rgba(255, 255, 255, 0.5) inset; + -webkit-transition: all 0.1s linear; + -moz-transition: all 0.1s linear; + transition: all 0.1s linear; + outline-none: false; +} + +.btn-hover { + background: #2e8ece; + color: white; +} + +.btn:hover { + background: #2cc36b; + color: white; +} +.btn:focus { + background: #2cc36b; + color: white; + outline: 0; +} +.btn:active { + border-top: solid 3px rgba(0, 0, 0, 0.1); + border-bottom: solid 1px rgba(0, 0, 0, 0.1); + box-shadow: 0px 1px 2px -1px rgba(0, 0, 0, 0.5) inset; +} +.btn[disabled] { + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: alpha(opacity=40); + opacity: 0.4; + cursor: not-allowed; + box-shadow: none; +} +.btn:visited { + color: white; +} + +.btn-disabled { + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: alpha(opacity=40); + opacity: 0.4; + cursor: not-allowed; + box-shadow: none; +} +.btn-disabled:hover, .btn-disabled:focus, .btn-disabled:active { + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: alpha(opacity=40); + opacity: 0.4; + cursor: not-allowed; + box-shadow: none; +} + +/* Firefox: Get rid of the inner focus border */ +.btn::-moz-focus-inner { + padding: 0; + border: 0; +} + +.btn-small { + font-size: 80%; +} + +.btn-info { + background-color: #2980b9 !important; +} +.btn-info:hover { + background-color: #2e8ece !important; +} + +.btn-neutral { + background-color: #f3f6f6 !important; + color: #404040 !important; +} +.btn-neutral:hover { + background-color: #e5ebeb !important; + color: #404040; +} +.btn-neutral:visited { + color: #404040 !important; +} + +.btn-success { + background-color: #27ae60 !important; +} +.btn-success:hover { + background-color: #229955 !important; +} + +.btn-danger { + background-color: #e74c3c !important; +} +.btn-danger:hover { + background-color: #ea6153 !important; +} + +.btn-warning { + background-color: #e67e22 !important; +} +.btn-warning:hover { + background-color: #e98b39 !important; +} + +.btn-invert { + background-color: #343131; +} +.btn-invert:hover { + background-color: #413d3d !important; +} + +.btn-link { + background-color: transparent !important; + color: #2980b9; + border-color: transparent; + box-shadow: none; +} +.btn-link:hover { + background-color: transparent !important; + color: #409ad5; + border-color: transparent; + box-shadow: none; +} +.btn-link:active { + background-color: transparent !important; + border-color: transparent; + border-top: solid 1px transparent; + border-bottom: solid 3px transparent; + box-shadow: none; +} +.btn-link:visited { + color: #9b59b6; +} + +.wy-btn-group .btn, .wy-control .btn { + vertical-align: middle; +} + +.wy-btn-group { + margin-bottom: 24px; + *zoom: 1; +} +.wy-btn-group:before, .wy-btn-group:after { + display: table; + content: ""; +} +.wy-btn-group:after { + clear: both; +} + +.wy-dropdown { + position: relative; + display: inline-block; +} + +.wy-dropdown-menu { + position: absolute; + top: 100%; + left: 0; + display: none; + float: left; + min-width: 100%; + background: #fcfcfc; + z-index: 100; + border: solid 1px #cfd7dd; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.1); + padding: 12px; +} +.wy-dropdown-menu > dd > a { + display: block; + clear: both; + color: #404040; + white-space: nowrap; + font-size: 90%; + padding: 0 12px; +} +.wy-dropdown-menu > dd > a:hover { + background: #2980b9; + color: white; +} +.wy-dropdown-menu > dd.divider { + border-top: solid 1px #cfd7dd; + margin: 6px 0; +} +.wy-dropdown-menu > dd.search { + padding-bottom: 12px; +} +.wy-dropdown-menu > dd.search input[type="search"] { + width: 100%; +} +.wy-dropdown-menu > dd.call-to-action { + background: #e3e3e3; + text-transform: uppercase; + font-weight: 500; + font-size: 80%; +} +.wy-dropdown-menu > dd.call-to-action:hover { + background: #e3e3e3; +} +.wy-dropdown-menu > dd.call-to-action .btn { + color: white; +} + +.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu { + background: #fcfcfc; + margin-top: 2px; +} +.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a { + padding: 6px 12px; +} +.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover { + background: #2980b9; + color: white; +} + +.wy-dropdown.wy-dropdown-left .wy-dropdown-menu { + right: 0; + text-align: right; +} + +.wy-dropdown-arrow:before { + content: " "; + border-bottom: 5px solid whitesmoke; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + position: absolute; + display: block; + top: -4px; + left: 50%; + margin-left: -3px; +} +.wy-dropdown-arrow.wy-dropdown-arrow-left:before { + left: 11px; +} + +.wy-form-stacked select { + display: block; +} + +.wy-form-aligned input, .wy-form-aligned textarea, .wy-form-aligned select, .wy-form-aligned .wy-help-inline, .wy-form-aligned label { + display: inline-block; + *display: inline; + *zoom: 1; + vertical-align: middle; +} + +.wy-form-aligned .wy-control-group > label { + display: inline-block; + vertical-align: middle; + width: 10em; + margin: 0.5em 1em 0 0; + float: left; +} +.wy-form-aligned .wy-control { + float: left; +} +.wy-form-aligned .wy-control label { + display: block; +} +.wy-form-aligned .wy-control select { + margin-top: 0.5em; +} + +fieldset { + border: 0; + margin: 0; + padding: 0; +} + +legend { + display: block; + width: 100%; + border: 0; + padding: 0; + white-space: normal; + margin-bottom: 24px; + font-size: 150%; + *margin-left: -7px; +} + +label { + display: block; + margin: 0 0 0.3125em 0; + color: #999999; + font-size: 90%; +} + +button, input, select, textarea { + font-size: 100%; + margin: 0; + vertical-align: baseline; + *vertical-align: middle; +} + +button, input { + line-height: normal; +} + +button { + -webkit-appearance: button; + cursor: pointer; + *overflow: visible; +} + +button::-moz-focus-inner, input::-moz-focus-inner { + border: 0; + padding: 0; +} + +button[disabled] { + cursor: default; +} + +input[type="button"], input[type="reset"], input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; + *overflow: visible; +} +input[type="text"], input[type="password"], input[type="email"], input[type="url"], input[type="date"], input[type="month"], input[type="time"], input[type="datetime"], input[type="datetime-local"], input[type="week"], input[type="number"], input[type="search"], input[type="tel"], input[type="color"] { + -webkit-appearance: none; + padding: 6px; + display: inline-block; + border: 1px solid #cccccc; + font-size: 80%; + font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; + box-shadow: inset 0 1px 3px #dddddd; + border-radius: 0; + -webkit-transition: border 0.3s linear; + -moz-transition: border 0.3s linear; + transition: border 0.3s linear; +} +input[type="datetime-local"] { + padding: 0.34375em 0.625em; +} +input[disabled] { + cursor: default; +} +input[type="checkbox"], input[type="radio"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0; + margin-right: 0.3125em; + *height: 13px; + *width: 13px; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +input[type="text"]:focus, input[type="password"]:focus, input[type="email"]:focus, input[type="url"]:focus, input[type="date"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="week"]:focus, input[type="number"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="color"]:focus { + outline: 0; + outline: thin dotted \9; + border-color: #333333; +} +input.no-focus:focus { + border-color: #cccccc !important; +} +input[type="file"]:focus, input[type="radio"]:focus, input[type="checkbox"]:focus { + outline: thin dotted #333333; + outline: 1px auto #129fea; +} +input[type="text"][disabled], input[type="password"][disabled], input[type="email"][disabled], input[type="url"][disabled], input[type="date"][disabled], input[type="month"][disabled], input[type="time"][disabled], input[type="datetime"][disabled], input[type="datetime-local"][disabled], input[type="week"][disabled], input[type="number"][disabled], input[type="search"][disabled], input[type="tel"][disabled], input[type="color"][disabled] { + cursor: not-allowed; + background-color: #f3f6f6; + color: #cad2d3; +} + +input:focus:invalid, textarea:focus:invalid, select:focus:invalid { + color: #e74c3c; + border: 1px solid #e74c3c; +} + +input:focus:invalid:focus, textarea:focus:invalid:focus, select:focus:invalid:focus { + border-color: #e74c3c; +} + +input[type="file"]:focus:invalid:focus, input[type="radio"]:focus:invalid:focus, input[type="checkbox"]:focus:invalid:focus { + outline-color: #e74c3c; +} + +input.wy-input-large { + padding: 12px; + font-size: 100%; +} + +textarea { + overflow: auto; + vertical-align: top; + width: 100%; +} + +select, textarea { + padding: 0.5em 0.625em; + display: inline-block; + border: 1px solid #cccccc; + font-size: 0.8em; + box-shadow: inset 0 1px 3px #dddddd; + -webkit-transition: border 0.3s linear; + -moz-transition: border 0.3s linear; + transition: border 0.3s linear; +} + +select { + border: 1px solid #cccccc; + background-color: white; +} +select[multiple] { + height: auto; +} + +select:focus, textarea:focus { + outline: 0; +} + +select[disabled], textarea[disabled], input[readonly], select[readonly], textarea[readonly] { + cursor: not-allowed; + background-color: white; + color: #cad2d3; + border-color: transparent; +} + +.wy-checkbox, .wy-radio { + margin: 0.5em 0; + color: #404040; + display: block; +} + +.wy-form-message-inline { + display: inline-block; + *display: inline; + *zoom: 1; + vertical-align: middle; +} + +.wy-input-prefix, .wy-input-suffix { + white-space: nowrap; +} +.wy-input-prefix .wy-input-context, .wy-input-suffix .wy-input-context { + padding: 6px; + display: inline-block; + font-size: 80%; + background-color: #f3f6f6; + border: solid 1px #cccccc; + color: #999999; +} + +.wy-input-suffix .wy-input-context { + border-left: 0; +} + +.wy-input-prefix .wy-input-context { + border-right: 0; +} + +.wy-inline-validate { + white-space: nowrap; +} +.wy-inline-validate .wy-input-context { + padding: 0.5em 0.625em; + display: inline-block; + font-size: 80%; +} + +.wy-inline-validate.wy-inline-validate-success .wy-input-context { + color: #27ae60; +} + +.wy-inline-validate.wy-inline-validate-danger .wy-input-context { + color: #e74c3c; +} + +.wy-inline-validate.wy-inline-validate-warning .wy-input-context { + color: #e67e22; +} + +.wy-inline-validate.wy-inline-validate-info .wy-input-context { + color: #2980b9; +} + +.wy-control-group { + margin-bottom: 24px; + *zoom: 1; + max-width: 68em; + margin-left: auto; + margin-right: auto; + *zoom: 1; +} +.wy-control-group:before, .wy-control-group:after { + display: table; + content: ""; +} +.wy-control-group:after { + clear: both; +} +.wy-control-group:before, .wy-control-group:after { + display: table; + content: ""; +} +.wy-control-group:after { + clear: both; +} + +.wy-control-group.wy-control-group-error .wy-form-message, .wy-control-group.wy-control-group-error > label { + color: #e74c3c; +} +.wy-control-group.wy-control-group-error input[type="text"], .wy-control-group.wy-control-group-error input[type="password"], .wy-control-group.wy-control-group-error input[type="email"], .wy-control-group.wy-control-group-error input[type="url"], .wy-control-group.wy-control-group-error input[type="date"], .wy-control-group.wy-control-group-error input[type="month"], .wy-control-group.wy-control-group-error input[type="time"], .wy-control-group.wy-control-group-error input[type="datetime"], .wy-control-group.wy-control-group-error input[type="datetime-local"], .wy-control-group.wy-control-group-error input[type="week"], .wy-control-group.wy-control-group-error input[type="number"], .wy-control-group.wy-control-group-error input[type="search"], .wy-control-group.wy-control-group-error input[type="tel"], .wy-control-group.wy-control-group-error input[type="color"] { + border: solid 1px #e74c3c; +} +.wy-control-group.wy-control-group-error textarea { + border: solid 1px #e74c3c; +} + +.wy-control-group.wy-control-group-required > label:after { + content: " *"; + color: #e74c3c; +} + +.wy-control-group .wy-form-full, .wy-control-group .wy-form-halves, .wy-control-group .wy-form-thirds { + padding-bottom: 12px; +} +.wy-control-group .wy-form-full select, .wy-control-group .wy-form-halves select, .wy-control-group .wy-form-thirds select { + width: 100%; +} +.wy-control-group .wy-form-full input[type="text"], .wy-control-group .wy-form-full input[type="password"], .wy-control-group .wy-form-full input[type="email"], .wy-control-group .wy-form-full input[type="url"], .wy-control-group .wy-form-full input[type="date"], .wy-control-group .wy-form-full input[type="month"], .wy-control-group .wy-form-full input[type="time"], .wy-control-group .wy-form-full input[type="datetime"], .wy-control-group .wy-form-full input[type="datetime-local"], .wy-control-group .wy-form-full input[type="week"], .wy-control-group .wy-form-full input[type="number"], .wy-control-group .wy-form-full input[type="search"], .wy-control-group .wy-form-full input[type="tel"], .wy-control-group .wy-form-full input[type="color"], .wy-control-group .wy-form-halves input[type="text"], .wy-control-group .wy-form-halves input[type="password"], .wy-control-group .wy-form-halves input[type="email"], .wy-control-group .wy-form-halves input[type="url"], .wy-control-group .wy-form-halves input[type="date"], .wy-control-group .wy-form-halves input[type="month"], .wy-control-group .wy-form-halves input[type="time"], .wy-control-group .wy-form-halves input[type="datetime"], .wy-control-group .wy-form-halves input[type="datetime-local"], .wy-control-group .wy-form-halves input[type="week"], .wy-control-group .wy-form-halves input[type="number"], .wy-control-group .wy-form-halves input[type="search"], .wy-control-group .wy-form-halves input[type="tel"], .wy-control-group .wy-form-halves input[type="color"], .wy-control-group .wy-form-thirds input[type="text"], .wy-control-group .wy-form-thirds input[type="password"], .wy-control-group .wy-form-thirds input[type="email"], .wy-control-group .wy-form-thirds input[type="url"], .wy-control-group .wy-form-thirds input[type="date"], .wy-control-group .wy-form-thirds input[type="month"], .wy-control-group .wy-form-thirds input[type="time"], .wy-control-group .wy-form-thirds input[type="datetime"], .wy-control-group .wy-form-thirds input[type="datetime-local"], .wy-control-group .wy-form-thirds input[type="week"], .wy-control-group .wy-form-thirds input[type="number"], .wy-control-group .wy-form-thirds input[type="search"], .wy-control-group .wy-form-thirds input[type="tel"], .wy-control-group .wy-form-thirds input[type="color"] { + width: 100%; +} + +.wy-control-group .wy-form-full { + display: block; + float: left; + margin-right: 2.35765%; + width: 100%; + margin-right: 0; +} +.wy-control-group .wy-form-full:last-child { + margin-right: 0; +} + +.wy-control-group .wy-form-halves { + display: block; + float: left; + margin-right: 2.35765%; + width: 48.82117%; +} +.wy-control-group .wy-form-halves:last-child { + margin-right: 0; +} +.wy-control-group .wy-form-halves:nth-of-type(2n) { + margin-right: 0; +} +.wy-control-group .wy-form-halves:nth-of-type(2n+1) { + clear: left; +} + +.wy-control-group .wy-form-thirds { + display: block; + float: left; + margin-right: 2.35765%; + width: 31.76157%; +} +.wy-control-group .wy-form-thirds:last-child { + margin-right: 0; +} +.wy-control-group .wy-form-thirds:nth-of-type(3n) { + margin-right: 0; +} +.wy-control-group .wy-form-thirds:nth-of-type(3n+1) { + clear: left; +} + +.wy-control-group.wy-control-group-no-input .wy-control { + margin: 0.5em 0 0 0; + font-size: 90%; +} + +.wy-control-group.fluid-input input[type="text"], .wy-control-group.fluid-input input[type="password"], .wy-control-group.fluid-input input[type="email"], .wy-control-group.fluid-input input[type="url"], .wy-control-group.fluid-input input[type="date"], .wy-control-group.fluid-input input[type="month"], .wy-control-group.fluid-input input[type="time"], .wy-control-group.fluid-input input[type="datetime"], .wy-control-group.fluid-input input[type="datetime-local"], .wy-control-group.fluid-input input[type="week"], .wy-control-group.fluid-input input[type="number"], .wy-control-group.fluid-input input[type="search"], .wy-control-group.fluid-input input[type="tel"], .wy-control-group.fluid-input input[type="color"] { + width: 100%; +} + +.wy-form-message-inline { + display: inline-block; + padding-left: 0.3em; + color: #666666; + vertical-align: middle; + font-size: 90%; +} + +.wy-form-message { + display: block; + color: #cccccc; + font-size: 70%; + margin-top: 0.3125em; + font-style: italic; +} + +.wy-tag-input-group { + padding: 4px 4px 0px 4px; + display: inline-block; + border: 1px solid #cccccc; + font-size: 80%; + font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; + box-shadow: inset 0 1px 3px #dddddd; + background: white; + -webkit-transition: border 0.3s linear; + -moz-transition: border 0.3s linear; + transition: border 0.3s linear; +} +.wy-tag-input-group .wy-tag { + display: inline-block; + background-color: rgba(0, 0, 0, 0.1); + padding: 0.5em 0.625em; + border-radius: 2px; + position: relative; + margin-bottom: 4px; +} +.wy-tag-input-group .wy-tag .wy-tag-remove { + color: #cccccc; + margin-left: 5px; +} +.wy-tag-input-group .wy-tag .wy-tag-remove:hover { + color: #e74c3c; +} +.wy-tag-input-group label { + margin-left: 5px; + display: inline-block; + margin-bottom: 0; +} +.wy-tag-input-group input { + border: none; + font-size: 100%; + margin-bottom: 4px; + box-shadow: none; +} + +.wy-form-upload { + border: solid 1px #cccccc; + border-bottom: solid 3px #cccccc; + background-color: #f3f6f6; + padding: 24px; + display: inline-block; + text-align: center; + cursor: pointer; + color: #404040; + -webkit-transition: border-color 0.1s ease-in; + -moz-transition: border-color 0.1s ease-in; + transition: border-color 0.1s ease-in; + *zoom: 1; +} +.wy-form-upload:before, .wy-form-upload:after { + display: table; + content: ""; +} +.wy-form-upload:after { + clear: both; +} +@media screen and (max-width: 480px) { + .wy-form-upload { + width: 100%; + } +} +.wy-form-upload .image-drop { + display: none; +} +.wy-form-upload .image-desktop { + display: none; +} +.wy-form-upload .image-loading { + display: none; +} +.wy-form-upload .wy-form-upload-icon { + display: block; + font-size: 32px; + color: #b3b3b3; +} +.wy-form-upload .image-drop .wy-form-upload-icon { + color: #27ae60; +} +.wy-form-upload p { + font-size: 90%; +} +.wy-form-upload .wy-form-upload-image { + float: left; + margin-right: 24px; +} +@media screen and (max-width: 480px) { + .wy-form-upload .wy-form-upload-image { + width: 100%; + margin-bottom: 24px; + } +} +.wy-form-upload img { + max-width: 125px; + max-height: 125px; + opacity: 0.9; + -webkit-transition: opacity 0.1s ease-in; + -moz-transition: opacity 0.1s ease-in; + transition: opacity 0.1s ease-in; +} +.wy-form-upload .wy-form-upload-content { + float: left; +} +@media screen and (max-width: 480px) { + .wy-form-upload .wy-form-upload-content { + width: 100%; + } +} + +.wy-form-upload:hover { + border-color: #b3b3b3; + color: #404040; +} +.wy-form-upload:hover .image-desktop { + display: block; +} +.wy-form-upload:hover .image-drag { + display: none; +} +.wy-form-upload:hover img { + opacity: 1; +} + +.wy-form-upload:active { + border-top: solid 3px #cccccc; + border-bottom: solid 1px #cccccc; +} + +.wy-form-upload.wy-form-upload-big { + width: 100%; + text-align: center; + padding: 72px; +} +.wy-form-upload.wy-form-upload-big .wy-form-upload-content { + float: none; +} + +.wy-form-upload.wy-form-upload-file p { + margin-bottom: 0; +} +.wy-form-upload.wy-form-upload-file .wy-form-upload-icon { + display: inline-block; + font-size: inherit; +} + +.wy-form-upload.wy-form-upload-drop { + background-color: #ddf7e8; +} +.wy-form-upload.wy-form-upload-drop .image-drop { + display: block; +} +.wy-form-upload.wy-form-upload-drop .image-desktop { + display: none; +} +.wy-form-upload.wy-form-upload-drop .image-drag { + display: none; +} + +.wy-form-upload.wy-form-upload-loading .image-drag { + display: none; +} +.wy-form-upload.wy-form-upload-loading .image-desktop { + display: none; +} +.wy-form-upload.wy-form-upload-loading .image-loading { + display: block; +} +.wy-form-upload.wy-form-upload-loading .wy-input-prefix { + display: none; +} +.wy-form-upload.wy-form-upload-loading p { + margin-bottom: 0; +} + +.rotate-90 { + -webkit-transform: rotate(90deg); + -moz-transform: rotate(90deg); + -ms-transform: rotate(90deg); + -o-transform: rotate(90deg); + transform: rotate(90deg); +} + +.rotate-180 { + -webkit-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -o-transform: rotate(180deg); + transform: rotate(180deg); +} + +.rotate-270 { + -webkit-transform: rotate(270deg); + -moz-transform: rotate(270deg); + -ms-transform: rotate(270deg); + -o-transform: rotate(270deg); + transform: rotate(270deg); +} + +.mirror { + -webkit-transform: scaleX(-1); + -moz-transform: scaleX(-1); + -ms-transform: scaleX(-1); + -o-transform: scaleX(-1); + transform: scaleX(-1); +} +.mirror.rotate-90 { + -webkit-transform: scaleX(-1) rotate(90deg); + -moz-transform: scaleX(-1) rotate(90deg); + -ms-transform: scaleX(-1) rotate(90deg); + -o-transform: scaleX(-1) rotate(90deg); + transform: scaleX(-1) rotate(90deg); +} +.mirror.rotate-180 { + -webkit-transform: scaleX(-1) rotate(180deg); + -moz-transform: scaleX(-1) rotate(180deg); + -ms-transform: scaleX(-1) rotate(180deg); + -o-transform: scaleX(-1) rotate(180deg); + transform: scaleX(-1) rotate(180deg); +} +.mirror.rotate-270 { + -webkit-transform: scaleX(-1) rotate(270deg); + -moz-transform: scaleX(-1) rotate(270deg); + -ms-transform: scaleX(-1) rotate(270deg); + -o-transform: scaleX(-1) rotate(270deg); + transform: scaleX(-1) rotate(270deg); +} + +.wy-form-gallery-manage { + margin-left: -12px; + margin-right: -12px; +} +.wy-form-gallery-manage li { + float: left; + padding: 12px; + width: 20%; + cursor: pointer; +} +@media screen and (max-width: 768px) { + .wy-form-gallery-manage li { + width: 25%; + } +} +@media screen and (max-width: 480px) { + .wy-form-gallery-manage li { + width: 50%; + } +} +.wy-form-gallery-manage li:active { + cursor: move; +} +.wy-form-gallery-manage li > a { + padding: 12px; + background-color: white; + border: solid 1px #e1e4e5; + border-bottom: solid 3px #e1e4e5; + display: inline-block; + -webkit-transition: all 0.1s ease-in; + -moz-transition: all 0.1s ease-in; + transition: all 0.1s ease-in; +} +.wy-form-gallery-manage li > a:active { + border: solid 1px #cccccc; + border-top: solid 3px #cccccc; +} +.wy-form-gallery-manage img { + width: 100%; + -webkit-transition: all 0.05s ease-in; + -moz-transition: all 0.05s ease-in; + transition: all 0.05s ease-in; +} + +li.wy-form-gallery-edit { + position: relative; + color: white; + padding: 24px; + width: 100%; + display: block; + background-color: #343131; + border-radius: 4px; +} +li.wy-form-gallery-edit .arrow { + position: absolute; + display: block; + top: -50px; + left: 50%; + margin-left: -25px; + z-index: 500; + height: 0; + width: 0; + border-color: transparent; + border-style: solid; + border-width: 25px; + border-bottom-color: #343131; +} + +@media only screen and (max-width: 480px) { + .wy-form button[type="submit"] { + margin: 0.7em 0 0; + } + .wy-form input[type="text"], .wy-form input[type="password"], .wy-form input[type="email"], .wy-form input[type="url"], .wy-form input[type="date"], .wy-form input[type="month"], .wy-form input[type="time"], .wy-form input[type="datetime"], .wy-form input[type="datetime-local"], .wy-form input[type="week"], .wy-form input[type="number"], .wy-form input[type="search"], .wy-form input[type="tel"], .wy-form input[type="color"] { + margin-bottom: 0.3em; + display: block; + } + .wy-form label { + margin-bottom: 0.3em; + display: block; + } + + .wy-form input[type="password"], .wy-form input[type="email"], .wy-form input[type="url"], .wy-form input[type="date"], .wy-form input[type="month"], .wy-form input[type="time"], .wy-form input[type="datetime"], .wy-form input[type="datetime-local"], .wy-form input[type="week"], .wy-form input[type="number"], .wy-form input[type="search"], .wy-form input[type="tel"], .wy-form input[type="color"] { + margin-bottom: 0; + } + + .wy-form-aligned .wy-control-group label { + margin-bottom: 0.3em; + text-align: left; + display: block; + width: 100%; + } + .wy-form-aligned .wy-controls { + margin: 1.5em 0 0 0; + } + + /* NOTE: wy-help-inline is deprecated. Use .wy-form-message-inline instead. */ + .wy-form .wy-help-inline, .wy-form-message-inline, .wy-form-message { + display: block; + font-size: 80%; + /* Increased bottom padding to make it group with its related input element. */ + padding: 0.2em 0 0.8em; + } +} +@media screen and (max-width: 768px) { + .tablet-hide { + display: none; + } +} + +@media screen and (max-width: 480px) { + .mobile-hide { + display: none; + } +} + +.float-left { + float: left; +} + +.float-right { + float: right; +} + +.full-width { + width: 100%; +} + +.wy-grid-one-col { + *zoom: 1; + max-width: 68em; + margin-left: auto; + margin-right: auto; + max-width: 1066px; + margin-top: 1.618em; +} +.wy-grid-one-col:before, .wy-grid-one-col:after { + display: table; + content: ""; +} +.wy-grid-one-col:after { + clear: both; +} +.wy-grid-one-col section { + display: block; + float: left; + margin-right: 2.35765%; + width: 100%; + background: #fcfcfc; + padding: 1.618em; + margin-right: 0; +} +.wy-grid-one-col section:last-child { + margin-right: 0; +} + +.wy-grid-index-card { + *zoom: 1; + max-width: 68em; + margin-left: auto; + margin-right: auto; + max-width: 460px; + margin-top: 1.618em; + background: #fcfcfc; + padding: 1.618em; +} +.wy-grid-index-card:before, .wy-grid-index-card:after { + display: table; + content: ""; +} +.wy-grid-index-card:after { + clear: both; +} +.wy-grid-index-card header, .wy-grid-index-card section, .wy-grid-index-card aside { + display: block; + float: left; + margin-right: 2.35765%; + width: 100%; +} +.wy-grid-index-card header:last-child, .wy-grid-index-card section:last-child, .wy-grid-index-card aside:last-child { + margin-right: 0; +} +.wy-grid-index-card.twocol { + max-width: 768px; +} +.wy-grid-index-card.twocol section { + display: block; + float: left; + margin-right: 2.35765%; + width: 48.82117%; +} +.wy-grid-index-card.twocol section:last-child { + margin-right: 0; +} +.wy-grid-index-card.twocol aside { + display: block; + float: left; + margin-right: 2.35765%; + width: 48.82117%; +} +.wy-grid-index-card.twocol aside:last-child { + margin-right: 0; +} + +.wy-grid-search-filter { + *zoom: 1; + max-width: 68em; + margin-left: auto; + margin-right: auto; + margin-bottom: 24px; +} +.wy-grid-search-filter:before, .wy-grid-search-filter:after { + display: table; + content: ""; +} +.wy-grid-search-filter:after { + clear: both; +} +.wy-grid-search-filter .wy-grid-search-filter-input { + display: block; + float: left; + margin-right: 2.35765%; + width: 74.41059%; +} +.wy-grid-search-filter .wy-grid-search-filter-input:last-child { + margin-right: 0; +} +.wy-grid-search-filter .wy-grid-search-filter-btn { + display: block; + float: left; + margin-right: 2.35765%; + width: 23.23176%; +} +.wy-grid-search-filter .wy-grid-search-filter-btn:last-child { + margin-right: 0; +} + +.wy-table, .rst-content table.docutils, .rst-content table.field-list { + /* Remove spacing between table cells (from Normalize.css) */ + border-collapse: collapse; + border-spacing: 0; + empty-cells: show; + margin-bottom: 24px; +} +.wy-table caption, .rst-content table.docutils caption, .rst-content table.field-list caption { + color: black; + font: italic 85%/1 arial, sans-serif; + padding: 1em 0; + text-align: center; +} +.wy-table td, .rst-content table.docutils td, .rst-content table.field-list td, .wy-table th, .rst-content table.docutils th, .rst-content table.field-list th { + font-size: 90%; + margin: 0; + overflow: visible; + padding: 8px 16px; +} +.wy-table td:first-child, .rst-content table.docutils td:first-child, .rst-content table.field-list td:first-child, .wy-table th:first-child, .rst-content table.docutils th:first-child, .rst-content table.field-list th:first-child { + border-left-width: 0; +} +.wy-table thead, .rst-content table.docutils thead, .rst-content table.field-list thead { + color: black; + text-align: left; + vertical-align: bottom; + white-space: nowrap; +} +.wy-table thead th, .rst-content table.docutils thead th, .rst-content table.field-list thead th { + font-weight: bold; + border-bottom: solid 2px #e1e4e5; +} +.wy-table td, .rst-content table.docutils td, .rst-content table.field-list td { + background-color: transparent; + vertical-align: middle; +} + +.wy-table td p, .rst-content table.docutils td p, .rst-content table.field-list td p { + line-height: 18px; + margin-bottom: 0; +} + +.wy-table .wy-table-cell-min, .rst-content table.docutils .wy-table-cell-min, .rst-content table.field-list .wy-table-cell-min { + width: 1%; + padding-right: 0; +} +.wy-table .wy-table-cell-min input[type=checkbox], .rst-content table.docutils .wy-table-cell-min input[type=checkbox], .rst-content table.field-list .wy-table-cell-min input[type=checkbox], .wy-table .wy-table-cell-min input[type=checkbox], .rst-content table.docutils .wy-table-cell-min input[type=checkbox], .rst-content table.field-list .wy-table-cell-min input[type=checkbox] { + margin: 0; +} + +.wy-table-secondary { + color: gray; + font-size: 90%; +} + +.wy-table-tertiary { + color: gray; + font-size: 80%; +} + +/*striping: + * even - #fff (white) + * odd - #f2f2f2 (light gray) */ +.wy-table-odd td, .wy-table-striped tr:nth-child(2n-1) td, .rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td { + background-color: #f3f6f6; +} + +.wy-table-backed { + background-color: #f3f6f6; +} + +/* nth-child selector for modern browsers */ +/* BORDERED TABLES */ +.wy-table-bordered-all, .rst-content table.docutils { + border: 1px solid #e1e4e5; +} +.wy-table-bordered-all td, .rst-content table.docutils td { + border-bottom: 1px solid #e1e4e5; + border-left: 1px solid #e1e4e5; +} +.wy-table-bordered-all tbody > tr:last-child td, .rst-content table.docutils tbody > tr:last-child td { + border-bottom-width: 0; +} + +.wy-table-bordered { + border: 1px solid #e1e4e5; +} + +.wy-table-bordered-rows td { + border-bottom: 1px solid #e1e4e5; +} +.wy-table-bordered-rows tbody > tr:last-child td { + border-bottom-width: 0; +} + +.wy-table-horizontal tbody > tr:last-child td { + border-bottom-width: 0; +} +.wy-table-horizontal td, .wy-table-horizontal th { + border-width: 0 0 1px 0; + border-bottom: 1px solid #e1e4e5; +} +.wy-table-horizontal tbody > tr:last-child td { + border-bottom-width: 0; +} + +/* RESPONSIVE TABLES */ +.wy-table-responsive { + margin-bottom: 24px; + max-width: 100%; + overflow: auto; +} +.wy-table-responsive table { + margin-bottom: 0 !important; +} +.wy-table-responsive table td, .wy-table-responsive table th { + white-space: nowrap; +} + +html { + height: 100%; + overflow-x: hidden; +} + +body { + font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; + font-weight: normal; + color: #404040; + min-height: 100%; + overflow-x: hidden; + background: #edf0f2; +} + +a { + color: #2980b9; + text-decoration: none; +} +a:hover { + color: #3091d1; +} +a:visited { + color: #9b59b6; +} + +.link-danger { + color: #e74c3c; +} +.link-danger:hover { + color: #d62c1a; +} + +.text-left { + text-align: left; +} + +.text-center { + text-align: center; +} + +.text-right { + text-align: right; +} + +h1, h2, h3, h4, h5, h6, legend { + margin-top: 0; + font-weight: 700; + font-family: "Roboto Slab", "ff-tisa-web-pro", "Georgia", Arial, sans-serif; +} + +p { + line-height: 24px; + margin: 0; + font-size: 16px; + margin-bottom: 24px; +} + +h1 { + font-size: 175%; +} + +h2 { + font-size: 150%; +} + +h3 { + font-size: 125%; +} + +h4 { + font-size: 115%; +} + +h5 { + font-size: 110%; +} + +h6 { + font-size: 100%; +} + +small { + font-size: 80%; +} + +code, .rst-content tt { + white-space: nowrap; + max-width: 100%; + background: white; + border: solid 1px #e1e4e5; + font-size: 75%; + padding: 0 5px; + font-family: "Incosolata", "Consolata", "Monaco", monospace; + color: #e74c3c; + overflow-x: auto; +} +code.code-large, .rst-content tt.code-large { + font-size: 90%; +} + +.full-width { + width: 100%; +} + +.wy-plain-list-disc, .rst-content .section ul, .rst-content .toctree-wrapper ul { + list-style: disc; + line-height: 24px; + margin-bottom: 24px; +} + +.wy-plain-list-disc li, .rst-content .section ul li, .rst-content .toctree-wrapper ul li { + list-style: disc; + margin-left: 24px; +} +.wy-plain-list-disc li ul, .rst-content .section ul li ul, .rst-content .toctree-wrapper ul li ul { + margin-bottom: 0; +} +.wy-plain-list-disc li li, .rst-content .section ul li li, .rst-content .toctree-wrapper ul li li { + list-style: circle; +} +.wy-plain-list-disc li li li, .rst-content .section ul li li li, .rst-content .toctree-wrapper ul li li li { + list-style: square; +} + +.wy-plain-list-decimal, .rst-content .section ol, .rst-content ol.arabic { + list-style: decimal; + line-height: 24px; + margin-bottom: 24px; +} + +.wy-plain-list-decimal li, .rst-content .section ol li, .rst-content ol.arabic li { + list-style: decimal; + margin-left: 24px; +} + +.wy-type-large { + font-size: 120%; +} + +.wy-type-normal { + font-size: 100%; +} + +.wy-type-small { + font-size: 100%; +} + +.wy-type-strike { + text-decoration: line-through; +} + +.wy-text-warning { + color: #e67e22 !important; +} + +a.wy-text-warning:hover { + color: #eb9950 !important; +} + +.wy-text-info { + color: #2980b9 !important; +} + +a.wy-text-info:hover { + color: #409ad5 !important; +} + +.wy-text-success { + color: #27ae60 !important; +} + +a.wy-text-success:hover { + color: #36d278 !important; +} + +.wy-text-danger { + color: #e74c3c !important; +} + +a.wy-text-danger:hover { + color: #ed7669 !important; +} + +.wy-text-neutral { + color: #404040 !important; +} + +a.wy-text-neutral:hover { + color: #595959 !important; +} + +.codeblock-example { + border: 1px solid #e1e4e5; + border-bottom: none; + padding: 24px; + padding-top: 48px; + font-weight: 500; + background: white; + position: relative; +} +.codeblock-example:after { + content: "Example"; + position: absolute; + top: 0px; + left: 0px; + background: #9b59b6; + color: white; + padding: 6px 12px; +} +.codeblock-example.prettyprint-example-only { + border: 1px solid #e1e4e5; + margin-bottom: 24px; +} + +.codeblock, pre.literal-block, .rst-content .literal-block, div[class^='highlight'] { + border: 1px solid #e1e4e5; + padding: 0px; + overflow-x: auto; + background: white; + margin: 1px 0 24px 0; +} +.codeblock div[class^='highlight'], pre.literal-block div[class^='highlight'], .rst-content .literal-block div[class^='highlight'], div[class^='highlight'] div[class^='highlight'] { + border: none; + background: none; + margin: 0; +} + +div[class^='highlight'] td.code { + width: 100%; +} + +.linenodiv pre { + border-right: solid 1px #e6e9ea; + margin: 0; + padding: 12px 12px; + font-family: "Incosolata", "Consolata", "Monaco", monospace; + font-size: 12px; + line-height: 1.5; + color: #d9d9d9; +} + +div[class^='highlight'] pre { + white-space: pre; + margin: 0; + padding: 12px 12px; + font-family: "Incosolata", "Consolata", "Monaco", monospace; + font-size: 12px; + line-height: 1.5; + display: block; + overflow: auto; + color: #404040; +} + +@media print { + .codeblock, pre.literal-block, .rst-content .literal-block, div[class^='highlight'], div[class^='highlight'] pre { + white-space: pre-wrap; + } +} +.hll { + background-color: #ffffcc; + margin: 0 -12px; + padding: 0 12px; + display: block; +} + +.c { + color: #999988; + font-style: italic; +} + +.err { + color: #a61717; + background-color: #e3d2d2; +} + +.k { + font-weight: bold; +} + +.o { + font-weight: bold; +} + +.cm { + color: #999988; + font-style: italic; +} + +.cp { + color: #999999; + font-weight: bold; +} + +.c1 { + color: #999988; + font-style: italic; +} + +.cs { + color: #999999; + font-weight: bold; + font-style: italic; +} + +.gd { + color: black; + background-color: #ffdddd; +} + +.gd .x { + color: black; + background-color: #ffaaaa; +} + +.ge { + font-style: italic; +} + +.gr { + color: #aa0000; +} + +.gh { + color: #999999; +} + +.gi { + color: black; + background-color: #ddffdd; +} + +.gi .x { + color: black; + background-color: #aaffaa; +} + +.go { + color: #888888; +} + +.gp { + color: #555555; +} + +.gs { + font-weight: bold; +} + +.gu { + color: purple; + font-weight: bold; +} + +.gt { + color: #aa0000; +} + +.kc { + font-weight: bold; +} + +.kd { + font-weight: bold; +} + +.kn { + font-weight: bold; +} + +.kp { + font-weight: bold; +} + +.kr { + font-weight: bold; +} + +.kt { + color: #445588; + font-weight: bold; +} + +.m { + color: #009999; +} + +.s { + color: #dd1144; +} + +.n { + color: #333333; +} + +.na { + color: teal; +} + +.nb { + color: #0086b3; +} + +.nc { + color: #445588; + font-weight: bold; +} + +.no { + color: teal; +} + +.ni { + color: purple; +} + +.ne { + color: #990000; + font-weight: bold; +} + +.nf { + color: #990000; + font-weight: bold; +} + +.nn { + color: #555555; +} + +.nt { + color: navy; +} + +.nv { + color: teal; +} + +.ow { + font-weight: bold; +} + +.w { + color: #bbbbbb; +} + +.mf { + color: #009999; +} + +.mh { + color: #009999; +} + +.mi { + color: #009999; +} + +.mo { + color: #009999; +} + +.sb { + color: #dd1144; +} + +.sc { + color: #dd1144; +} + +.sd { + color: #dd1144; +} + +.s2 { + color: #dd1144; +} + +.se { + color: #dd1144; +} + +.sh { + color: #dd1144; +} + +.si { + color: #dd1144; +} + +.sx { + color: #dd1144; +} + +.sr { + color: #009926; +} + +.s1 { + color: #dd1144; +} + +.ss { + color: #990073; +} + +.bp { + color: #999999; +} + +.vc { + color: teal; +} + +.vg { + color: teal; +} + +.vi { + color: teal; +} + +.il { + color: #009999; +} + +.gc { + color: #999999; + background-color: #eaf2f5; +} + +.wy-breadcrumbs li { + display: inline-block; +} +.wy-breadcrumbs li.wy-breadcrumbs-aside { + float: right; +} +.wy-breadcrumbs li a { + display: inline-block; + padding: 5px; +} +.wy-breadcrumbs li a:first-child { + padding-left: 0; +} + +.wy-breadcrumbs-extra { + margin-bottom: 0; + color: #b3b3b3; + font-size: 80%; + display: inline-block; +} + +@media screen and (max-width: 480px) { + .wy-breadcrumbs-extra { + display: none; + } + + .wy-breadcrumbs li.wy-breadcrumbs-aside { + display: none; + } +} +@media print { + .wy-breadcrumbs li.wy-breadcrumbs-aside { + display: none; + } +} +.wy-affix { + position: fixed; + top: 1.618em; +} + +.wy-menu a:hover { + text-decoration: none; +} + +.wy-menu-horiz { + *zoom: 1; +} +.wy-menu-horiz:before, .wy-menu-horiz:after { + display: table; + content: ""; +} +.wy-menu-horiz:after { + clear: both; +} +.wy-menu-horiz ul, .wy-menu-horiz li { + display: inline-block; +} +.wy-menu-horiz li:hover { + background: rgba(255, 255, 255, 0.1); +} +.wy-menu-horiz li.divide-left { + border-left: solid 1px #404040; +} +.wy-menu-horiz li.divide-right { + border-right: solid 1px #404040; +} +.wy-menu-horiz a { + height: 32px; + display: inline-block; + line-height: 32px; + padding: 0 16px; +} + +.wy-menu-vertical header { + height: 32px; + display: inline-block; + line-height: 32px; + padding: 0 1.618em; + display: block; + font-weight: bold; + text-transform: uppercase; + font-size: 80%; + color: #2980b9; + white-space: nowrap; +} +.wy-menu-vertical ul { + margin-bottom: 0; +} +.wy-menu-vertical li.divide-top { + border-top: solid 1px #404040; +} +.wy-menu-vertical li.divide-bottom { + border-bottom: solid 1px #404040; +} +.wy-menu-vertical li.current { + background: #e3e3e3; +} +.wy-menu-vertical li.current a { + color: gray; + border-right: solid 1px #c9c9c9; + padding: 0.4045em 2.427em; +} +.wy-menu-vertical li.current a:hover { + background: #d6d6d6; +} +.wy-menu-vertical li.on a, .wy-menu-vertical li.current > a { + color: #404040; + padding: 0.4045em 1.618em; + font-weight: bold; + position: relative; + background: #fcfcfc; + border: none; + border-bottom: solid 1px #c9c9c9; + border-top: solid 1px #c9c9c9; + padding-left: 1.618em -4px; +} +.wy-menu-vertical li.on a:hover, .wy-menu-vertical li.current > a:hover { + background: #fcfcfc; +} +.wy-menu-vertical li.toctree-l2.current > a { + background: #c9c9c9; + padding: 0.4045em 2.427em; +} +.wy-menu-vertical li.current ul { + display: block; +} +.wy-menu-vertical li ul { + margin-bottom: 0; + display: none; +} +.wy-menu-vertical .local-toc li ul { + display: block; +} +.wy-menu-vertical li ul li a { + margin-bottom: 0; + color: #b3b3b3; + font-weight: normal; +} +.wy-menu-vertical a { + display: inline-block; + line-height: 18px; + padding: 0.4045em 1.618em; + display: block; + position: relative; + font-size: 90%; + color: #b3b3b3; +} +.wy-menu-vertical a:hover { + background-color: #4e4a4a; + cursor: pointer; +} +.wy-menu-vertical a:active { + background-color: #2980b9; + cursor: pointer; + color: white; +} + +.wy-side-nav-search { + z-index: 200; + background-color: #2980b9; + text-align: center; + padding: 0.809em; + display: block; + color: #fcfcfc; + margin-bottom: 0.809em; +} +.wy-side-nav-search input[type=text] { + width: 100%; + border-radius: 50px; + padding: 6px 12px; + border-color: #2472a4; +} +.wy-side-nav-search img { + display: block; + margin: auto auto 0.809em auto; + height: 45px; + width: 45px; + background-color: #2980b9; + padding: 5px; + border-radius: 100%; +} +.wy-side-nav-search > a, .wy-side-nav-search .wy-dropdown > a { + color: #fcfcfc; + font-size: 100%; + font-weight: bold; + display: inline-block; + padding: 4px 6px; + margin-bottom: 0.809em; +} +.wy-side-nav-search > a:hover, .wy-side-nav-search .wy-dropdown > a:hover { + background: rgba(255, 255, 255, 0.1); +} + +.wy-nav .wy-menu-vertical header { + color: #2980b9; +} +.wy-nav .wy-menu-vertical a { + color: #b3b3b3; +} +.wy-nav .wy-menu-vertical a:hover { + background-color: #2980b9; + color: white; +} + +[data-menu-wrap] { + -webkit-transition: all 0.2s ease-in; + -moz-transition: all 0.2s ease-in; + transition: all 0.2s ease-in; + position: absolute; + opacity: 1; + width: 100%; + opacity: 0; +} +[data-menu-wrap].move-center { + left: 0; + right: auto; + opacity: 1; +} +[data-menu-wrap].move-left { + right: auto; + left: -100%; + opacity: 0; +} +[data-menu-wrap].move-right { + right: -100%; + left: auto; + opacity: 0; +} + +.wy-body-for-nav { + background: left repeat-y #fcfcfc; + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxOERBMTRGRDBFMUUxMUUzODUwMkJCOThDMEVFNURFMCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoxOERBMTRGRTBFMUUxMUUzODUwMkJCOThDMEVFNURFMCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjE4REExNEZCMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjE4REExNEZDMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+EwrlwAAAAA5JREFUeNpiMDU0BAgwAAE2AJgB9BnaAAAAAElFTkSuQmCC); + background-size: 300px 1px; +} + +.wy-grid-for-nav { + position: absolute; + width: 100%; + height: 100%; +} + +.wy-nav-side { + position: absolute; + top: 0; + left: 0; + width: 300px; + overflow: hidden; + min-height: 100%; + background: #343131; + z-index: 200; +} + +.wy-nav-top { + display: none; + background: #2980b9; + color: white; + padding: 0.4045em 0.809em; + position: relative; + line-height: 50px; + text-align: center; + font-size: 100%; + *zoom: 1; +} +.wy-nav-top:before, .wy-nav-top:after { + display: table; + content: ""; +} +.wy-nav-top:after { + clear: both; +} +.wy-nav-top a { + color: white; + font-weight: bold; +} +.wy-nav-top img { + margin-right: 12px; + height: 45px; + width: 45px; + background-color: #2980b9; + padding: 5px; + border-radius: 100%; +} +.wy-nav-top i { + font-size: 30px; + float: left; + cursor: pointer; +} + +.wy-nav-content-wrap { + margin-left: 300px; + background: #fcfcfc; + min-height: 100%; +} + +.wy-nav-content { + padding: 1.618em 3.236em; + height: 100%; + max-width: 800px; + margin: auto; +} + +.wy-body-mask { + position: fixed; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.2); + display: none; + z-index: 499; +} +.wy-body-mask.on { + display: block; +} + +footer { + color: #999999; +} +footer p { + margin-bottom: 12px; +} + +.rst-footer-buttons { + *zoom: 1; +} +.rst-footer-buttons:before, .rst-footer-buttons:after { + display: table; + content: ""; +} +.rst-footer-buttons:after { + clear: both; +} + +#search-results .search li { + margin-bottom: 24px; + border-bottom: solid 1px #e1e4e5; + padding-bottom: 24px; +} +#search-results .search li:first-child { + border-top: solid 1px #e1e4e5; + padding-top: 24px; +} +#search-results .search li a { + font-size: 120%; + margin-bottom: 12px; + display: inline-block; +} +#search-results .context { + color: gray; + font-size: 90%; +} + +@media screen and (max-width: 768px) { + .wy-body-for-nav { + background: #fcfcfc; + } + + .wy-nav-top { + display: block; + } + + .wy-nav-side { + left: -300px; + } + .wy-nav-side.shift { + width: 85%; + left: 0; + } + + .wy-nav-content-wrap { + margin-left: 0; + } + .wy-nav-content-wrap .wy-nav-content { + padding: 1.618em; + } + .wy-nav-content-wrap.shift { + position: fixed; + min-width: 100%; + left: 85%; + top: 0; + height: 100%; + overflow: hidden; + } +} +@media screen and (min-width: 1400px) { + .wy-nav-content-wrap { + background: rgba(0, 0, 0, 0.05); + } + + .wy-nav-content { + margin: 0; + background: #fcfcfc; + } +} +@media print { + .wy-nav-side { + display: none; + } + + .wy-nav-content-wrap { + margin-left: 0; + } +} +nav.stickynav { + position: fixed; + top: 0; +} + +.rst-versions { + position: fixed; + bottom: 0; + left: 0; + width: 300px; + color: #fcfcfc; + background: #1f1d1d; + border-top: solid 10px #343131; + font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; + z-index: 400; +} +.rst-versions a { + color: #2980b9; + text-decoration: none; +} +.rst-versions .rst-badge-small { + display: none; +} +.rst-versions .rst-current-version { + padding: 12px; + background-color: #272525; + display: block; + text-align: right; + font-size: 90%; + cursor: pointer; + color: #27ae60; + *zoom: 1; +} +.rst-versions .rst-current-version:before, .rst-versions .rst-current-version:after { + display: table; + content: ""; +} +.rst-versions .rst-current-version:after { + clear: both; +} +.rst-versions .rst-current-version .fa, .rst-versions .rst-current-version .wy-dropdown .caret, .wy-dropdown .rst-versions .rst-current-version .caret, .rst-versions .rst-current-version .wy-inline-validate.wy-inline-validate-success .wy-input-context, .wy-inline-validate.wy-inline-validate-success .rst-versions .rst-current-version .wy-input-context, .rst-versions .rst-current-version .wy-inline-validate.wy-inline-validate-danger .wy-input-context, .wy-inline-validate.wy-inline-validate-danger .rst-versions .rst-current-version .wy-input-context, .rst-versions .rst-current-version .wy-inline-validate.wy-inline-validate-warning .wy-input-context, .wy-inline-validate.wy-inline-validate-warning .rst-versions .rst-current-version .wy-input-context, .rst-versions .rst-current-version .wy-inline-validate.wy-inline-validate-info .wy-input-context, .wy-inline-validate.wy-inline-validate-info .rst-versions .rst-current-version .wy-input-context, .rst-versions .rst-current-version .wy-tag-input-group .wy-tag .wy-tag-remove, .wy-tag-input-group .wy-tag .rst-versions .rst-current-version .wy-tag-remove, .rst-versions .rst-current-version .rst-content .admonition-title, .rst-content .rst-versions .rst-current-version .admonition-title, .rst-versions .rst-current-version .rst-content h1 .headerlink, .rst-content h1 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h2 .headerlink, .rst-content h2 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h3 .headerlink, .rst-content h3 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h4 .headerlink, .rst-content h4 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h5 .headerlink, .rst-content h5 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h6 .headerlink, .rst-content h6 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content dl dt .headerlink, .rst-content dl dt .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .icon { + color: #fcfcfc; +} +.rst-versions .rst-current-version .fa-book, .rst-versions .rst-current-version .icon-book { + float: left; +} +.rst-versions .rst-current-version .icon-book { + float: left; +} +.rst-versions .rst-current-version.rst-out-of-date { + background-color: #e74c3c; + color: white; +} +.rst-versions .rst-current-version.rst-active-old-version { + background-color: #f1c40f; + color: black; +} +.rst-versions.shift-up .rst-other-versions { + display: block; +} +.rst-versions .rst-other-versions { + font-size: 90%; + padding: 12px; + color: gray; + display: none; +} +.rst-versions .rst-other-versions hr { + display: block; + height: 1px; + border: 0; + margin: 20px 0; + padding: 0; + border-top: solid 1px #413d3d; +} +.rst-versions .rst-other-versions dd { + display: inline-block; + margin: 0; +} +.rst-versions .rst-other-versions dd a { + display: inline-block; + padding: 6px; + color: #fcfcfc; +} +.rst-versions.rst-badge { + width: auto; + bottom: 20px; + right: 20px; + left: auto; + border: none; + max-width: 300px; +} +.rst-versions.rst-badge .icon-book { + float: none; +} +.rst-versions.rst-badge .fa-book, .rst-versions.rst-badge .icon-book { + float: none; +} +.rst-versions.rst-badge.shift-up .rst-current-version { + text-align: right; +} +.rst-versions.rst-badge.shift-up .rst-current-version .fa-book, .rst-versions.rst-badge.shift-up .rst-current-version .icon-book { + float: left; +} +.rst-versions.rst-badge.shift-up .rst-current-version .icon-book { + float: left; +} +.rst-versions.rst-badge .rst-current-version { + width: auto; + height: 30px; + line-height: 30px; + padding: 0 6px; + display: block; + text-align: center; +} + +@media screen and (max-width: 768px) { + .rst-versions { + width: 85%; + display: none; + } + .rst-versions.shift { + display: block; + } + + img { + width: 100%; + height: auto; + } +} +.rst-content img { + max-width: 100%; + height: auto !important; +} +.rst-content div.figure { + margin-bottom: 24px; +} +.rst-content div.figure.align-center { + text-align: center; +} +.rst-content .section > img { + margin-bottom: 24px; +} +.rst-content blockquote { + margin-left: 24px; + line-height: 24px; + margin-bottom: 24px; +} +.rst-content .note .last, .rst-content .attention .last, .rst-content .caution .last, .rst-content .danger .last, .rst-content .error .last, .rst-content .hint .last, .rst-content .important .last, .rst-content .tip .last, .rst-content .warning .last, .rst-content .seealso .last { + margin-bottom: 0; +} +.rst-content .admonition-title:before { + margin-right: 4px; +} +.rst-content .admonition table { + border-color: rgba(0, 0, 0, 0.1); +} +.rst-content .admonition table td, .rst-content .admonition table th { + background: transparent !important; + border-color: rgba(0, 0, 0, 0.1) !important; +} +.rst-content .section ol.loweralpha, .rst-content .section ol.loweralpha li { + list-style: lower-alpha; +} +.rst-content .section ol.upperalpha, .rst-content .section ol.upperalpha li { + list-style: upper-alpha; +} +.rst-content .section ol p, .rst-content .section ul p { + margin-bottom: 12px; +} +.rst-content .line-block { + margin-left: 24px; +} +.rst-content .topic-title { + font-weight: bold; + margin-bottom: 12px; +} +.rst-content .toc-backref { + color: #404040; +} +.rst-content .align-right { + float: right; + margin: 0px 0px 24px 24px; +} +.rst-content .align-left { + float: left; + margin: 0px 24px 24px 0px; +} +.rst-content .align-center { + margin: auto; + display: block; +} +.rst-content h1 .headerlink, .rst-content h2 .headerlink, .rst-content h3 .headerlink, .rst-content h4 .headerlink, .rst-content h5 .headerlink, .rst-content h6 .headerlink, .rst-content dl dt .headerlink { + display: none; + visibility: hidden; + font-size: 14px; +} +.rst-content h1 .headerlink:after, .rst-content h2 .headerlink:after, .rst-content h3 .headerlink:after, .rst-content h4 .headerlink:after, .rst-content h5 .headerlink:after, .rst-content h6 .headerlink:after, .rst-content dl dt .headerlink:after { + visibility: visible; + content: "\f0c1"; + font-family: FontAwesome; + display: inline-block; +} +.rst-content h1:hover .headerlink, .rst-content h2:hover .headerlink, .rst-content h3:hover .headerlink, .rst-content h4:hover .headerlink, .rst-content h5:hover .headerlink, .rst-content h6:hover .headerlink, .rst-content dl dt:hover .headerlink { + display: inline-block; +} +.rst-content .sidebar { + float: right; + width: 40%; + display: block; + margin: 0 0 24px 24px; + padding: 24px; + background: #f3f6f6; + border: solid 1px #e1e4e5; +} +.rst-content .sidebar p, .rst-content .sidebar ul, .rst-content .sidebar dl { + font-size: 90%; +} +.rst-content .sidebar .last { + margin-bottom: 0; +} +.rst-content .sidebar .sidebar-title { + display: block; + font-family: "Roboto Slab", "ff-tisa-web-pro", "Georgia", Arial, sans-serif; + font-weight: bold; + background: #e1e4e5; + padding: 6px 12px; + margin: -24px; + margin-bottom: 24px; + font-size: 100%; +} +.rst-content .highlighted { + background: #f1c40f; + display: inline-block; + font-weight: bold; + padding: 0 6px; +} +.rst-content .footnote-reference, .rst-content .citation-reference { + vertical-align: super; + font-size: 90%; +} +.rst-content table.docutils.citation, .rst-content table.docutils.footnote { + background: none; + border: none; + color: #999999; +} +.rst-content table.docutils.citation td, .rst-content table.docutils.citation tr, .rst-content table.docutils.footnote td, .rst-content table.docutils.footnote tr { + border: none; + background-color: transparent !important; + white-space: normal; +} +.rst-content table.docutils.citation td.label, .rst-content table.docutils.footnote td.label { + padding-left: 0; + padding-right: 0; + vertical-align: top; +} +.rst-content table.field-list { + border: none; +} +.rst-content table.field-list td { + border: none; + padding-top: 5px; +} +.rst-content table.field-list .field-name { + padding-right: 10px; + text-align: left; + white-space: nowrap; +} +.rst-content table.field-list .field-body { + text-align: left; + padding-left: 0; +} +.rst-content tt { + color: black; +} +.rst-content tt big, .rst-content tt em { + font-size: 100% !important; + line-height: normal; +} +.rst-content tt .xref, a .rst-content tt { + font-weight: bold; +} +.rst-content a tt { + color: #2980b9; +} +.rst-content dl { + margin-bottom: 24px; +} +.rst-content dl dt { + font-weight: bold; +} +.rst-content dl p, .rst-content dl table, .rst-content dl ul, .rst-content dl ol { + margin-bottom: 12px !important; +} +.rst-content dl dd { + margin: 0 0 12px 24px; +} +.rst-content dl:not(.docutils) { + margin-bottom: 24px; +} +.rst-content dl:not(.docutils) dt { + display: inline-block; + margin: 6px 0; + font-size: 90%; + line-height: normal; + background: #e7f2fa; + color: #2980b9; + border-top: solid 3px #6ab0de; + padding: 6px; + position: relative; +} +.rst-content dl:not(.docutils) dt:before { + color: #6ab0de; +} +.rst-content dl:not(.docutils) dt .headerlink { + color: #404040; + font-size: 100% !important; +} +.rst-content dl:not(.docutils) dl dt { + margin-bottom: 6px; + border: none; + border-left: solid 3px #cccccc; + background: #f0f0f0; + color: gray; +} +.rst-content dl:not(.docutils) dl dt .headerlink { + color: #404040; + font-size: 100% !important; +} +.rst-content dl:not(.docutils) dt:first-child { + margin-top: 0; +} +.rst-content dl:not(.docutils) tt { + font-weight: bold; +} +.rst-content dl:not(.docutils) tt.descname, .rst-content dl:not(.docutils) tt.descclassname { + background-color: transparent; + border: none; + padding: 0; + font-size: 100% !important; +} +.rst-content dl:not(.docutils) tt.descname { + font-weight: bold; +} +.rst-content dl:not(.docutils) .optional { + display: inline-block; + padding: 0 4px; + color: black; + font-weight: bold; +} +.rst-content dl:not(.docutils) .property { + display: inline-block; + padding-right: 8px; +} +.rst-content .viewcode-link, .rst-content .viewcode-back { + display: inline-block; + color: #27ae60; + font-size: 80%; + padding-left: 24px; +} +.rst-content .viewcode-back { + display: block; + float: right; +} + +@media screen and (max-width: 480px) { + .rst-content .sidebar { + width: 100%; + } +} +span[id*='MathJax-Span'] { + color: #404040; +} diff --git a/docs/_themes/sphinx_rtd_theme/static/fonts/FontAwesome.otf b/docs/_themes/sphinx_rtd_theme/static/fonts/FontAwesome.otf new file mode 100644 index 0000000..8b0f54e Binary files /dev/null and b/docs/_themes/sphinx_rtd_theme/static/fonts/FontAwesome.otf differ diff --git a/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.eot b/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.eot new file mode 100644 index 0000000..7c79c6a Binary files /dev/null and b/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.eot differ diff --git a/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg b/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg new file mode 100644 index 0000000..45fdf33 --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg @@ -0,0 +1,414 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.ttf b/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.ttf new file mode 100644 index 0000000..e89738d Binary files /dev/null and b/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.ttf differ diff --git a/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.woff b/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.woff new file mode 100644 index 0000000..8c1748a Binary files /dev/null and b/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.woff differ diff --git a/docs/_themes/sphinx_rtd_theme/static/js/theme.js b/docs/_themes/sphinx_rtd_theme/static/js/theme.js new file mode 100644 index 0000000..60520cc --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/static/js/theme.js @@ -0,0 +1,47 @@ +$( document ).ready(function() { + // Shift nav in mobile when clicking the menu. + $(document).on('click', "[data-toggle='wy-nav-top']", function() { + $("[data-toggle='wy-nav-shift']").toggleClass("shift"); + $("[data-toggle='rst-versions']").toggleClass("shift"); + }); + // Close menu when you click a link. + $(document).on('click', ".wy-menu-vertical .current ul li a", function() { + $("[data-toggle='wy-nav-shift']").removeClass("shift"); + $("[data-toggle='rst-versions']").toggleClass("shift"); + }); + $(document).on('click', "[data-toggle='rst-current-version']", function() { + $("[data-toggle='rst-versions']").toggleClass("shift-up"); + }); + // Make tables responsive + $("table.docutils:not(.field-list)").wrap("
"); +}); + +window.SphinxRtdTheme = (function (jquery) { + var stickyNav = (function () { + var navBar, + win, + stickyNavCssClass = 'stickynav', + applyStickNav = function () { + if (navBar.height() <= win.height()) { + navBar.addClass(stickyNavCssClass); + } else { + navBar.removeClass(stickyNavCssClass); + } + }, + enable = function () { + applyStickNav(); + win.on('resize', applyStickNav); + }, + init = function () { + navBar = jquery('nav.wy-nav-side:first'); + win = jquery(window); + }; + jquery(init); + return { + enable : enable + }; + }()); + return { + StickyNav : stickyNav + }; +}($)); diff --git a/docs/_themes/sphinx_rtd_theme/theme.conf b/docs/_themes/sphinx_rtd_theme/theme.conf new file mode 100644 index 0000000..1ad1fa7 --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/theme.conf @@ -0,0 +1,9 @@ +[theme] +inherit = basic +stylesheet = css/theme.css + +[options] +typekit_id = hiw1hhg +analytics_id = +sticky_navigation = False +github_fork = hgrecco/pyvisa diff --git a/docs/_themes/sphinx_rtd_theme/versions.html b/docs/_themes/sphinx_rtd_theme/versions.html new file mode 100644 index 0000000..8b3eb79 --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/versions.html @@ -0,0 +1,37 @@ +{% if READTHEDOCS %} +{# Add rst-badge after rst-versions for small badge style. #} +
+ + Read the Docs + v: {{ current_version }} + + +
+
+
Versions
+ {% for slug, url in versions %} +
{{ slug }}
+ {% endfor %} +
+
+
Downloads
+ {% for type, url in downloads %} +
{{ type }}
+ {% endfor %} +
+
+
On Read the Docs
+
+ Project Home +
+
+ Builds +
+
+
+ Free document hosting provided by Read the Docs. + +
+
+{% endif %} + diff --git a/docs/api/constants.rst b/docs/api/constants.rst new file mode 100644 index 0000000..a3f14cb --- /dev/null +++ b/docs/api/constants.rst @@ -0,0 +1,45 @@ +.. _api_constants: + +.. py:module:: pyvisa.constants + +Constants module +---------------- + +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: diff --git a/docs/api/index.rst b/docs/api/index.rst new file mode 100644 index 0000000..88227de --- /dev/null +++ b/docs/api/index.rst @@ -0,0 +1,14 @@ +.. _api: + +=== +API +=== + + +.. toctree:: + :maxdepth: 1 + + visalibrarybase + resourcemanager + resources + constants diff --git a/docs/api/resourcemanager.rst b/docs/api/resourcemanager.rst new file mode 100644 index 0000000..a4cd468 --- /dev/null +++ b/docs/api/resourcemanager.rst @@ -0,0 +1,9 @@ +.. _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 diff --git a/docs/api/resources.rst b/docs/api/resources.rst new file mode 100644 index 0000000..54dd5bc --- /dev/null +++ b/docs/api/resources.rst @@ -0,0 +1,135 @@ +.. _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: + diff --git a/docs/api/visalibrarybase.rst b/docs/api/visalibrarybase.rst new file mode 100644 index 0000000..df8a24d --- /dev/null +++ b/docs/api/visalibrarybase.rst @@ -0,0 +1,9 @@ +.. _api_visalibrarybase: + + +Visa Library +------------ + +.. autoclass:: pyvisa.highlevel.VisaLibraryBase + :members: + diff --git a/docs/architecture.rst b/docs/architecture.rst new file mode 100644 index 0000000..3402a05 --- /dev/null +++ b/docs/architecture.rst @@ -0,0 +1,105 @@ +.. _architecture: + +Architecture +============ + +PyVISA implements convenient and Pythonic programming in three layers: + + 1. Low-level: A wrapper around the shared visa library. + + The wrapper defines the argument types and response types of each function, + as well as the conversions between Python objects and foreign types. + + You will normally not need to access these functions directly. If you do, + it probably means that we need to improve layer 2. + + All level 1 functions are **static methods** of :class:`pyvisa.highlevel.VisaLibrary`. + + .. warning:: Notice however that low-level functions might not be present in all backends. + For broader compatibility, do no use this layer. All the functionality should + is available via the next layer. + + + 2. Middle-level: A wrapping Python function for each function of the shared visa library. + + These functions call the low-level functions, adding some code to deal with + type conversions for functions that return values by reference. + These functions also have comprehensive and Python friendly documentation. + + You only need to access this layer if you want to control certain specific + aspects of the VISA library which are not implemented by the corresponding + resource class. + + All level 2 functions are **bound methods** of :class:`pyvisa.highlevel.VisaLibrary`. + + 3. High-level: An object-oriented layer for :class:`pyvisa.highlevel.ResourceManager` and :class:`pyvisa.resources.Resource` + + The ``ResourceManager`` implements methods to inspect connected resources. You also + use this object to open other resources instantiating the appropriate ``Resource`` + derived classes. + + ``Resource`` and the derived classes implement functions and attributes access + to the underlying resources in a Pythonic way. + +Most of the time you will only need to instantiate a ``ResourceManager``. For a given resource, +you will use the :meth:`pyvisa.highlevel.ResourceManager.open_resource` method to obtain the appropriate object. If needed, you will +be able to access the ``VisaLibrary`` object directly using the :attr:`pyvisa.highlevel.ResourceManager.visalib` attribute. + +The ``VisaLibrary`` does the low-level calls. In the default NI Backend, levels 1 and 2 are +implemented in the same package called :mod:`pyvisa.ctwrapper` (which stands for ctypes wrapper). +This package is included in PyVISA. + +Other backends can be used just by passing the name of the backend to ``ResourceManager`` +after the `@` symbol. See more information in :ref:`backends`. + + +Calling middle- and low-level functions +--------------------------------------- + +After you have instantiated the ``ResourceManager``:: + + >>> import visa + >>> rm = visa.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. + diff --git a/docs/backends.rst b/docs/backends.rst new file mode 100644 index 0000000..1aded42 --- /dev/null +++ b/docs/backends.rst @@ -0,0 +1,182 @@ +.. _backends: + + +A frontend for multiple backends +================================ + +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 NI-VISA is the +default backend (called **ni**) and is bundled with PyVISA for simplicity. + +You can specify the backend to use when you instantiate the resource manager using the +``@`` symbol. Remembering that **ni** is the default, this:: + + >>> import visa + >>> rm = visa.ResourceManager() + +is the same as this:: + + >>> import visa + >>> rm = visa.ResourceManager('@ni') + +You can still provide the path to the library if needed:: + + >>> import visa + >>> rm = visa.ResourceManager('/path/to/lib@ni') + +Under the hood, the :class:`pyvisa.highlevel.ResourceManager` looks for the requested backend and instantiate +the VISA library that it provides. + +PyVISA locates backends by name. If you do: + + >>> import visa + >>> rm = visa.ResourceManager('@somename') + +PyVISA will try to import a package/module named ``pyvisa-somename`` which should be +installed in your system. This is a loosly 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:: + + python -m visa 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 ``python -m visa 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:`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. + + +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): + diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..1a1d32d --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,297 @@ +# -*- 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 os +import pkg_resources +import datetime + + +# 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.0' + +# 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'] + +# 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 = pkg_resources.get_distribution(project).version +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 = ['_build'] + +# 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 = [] +html_theme_path = ['_themes'] + +# 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 = {} +html_sidebars = { + 'index': ['sidebarintro.html', 'sourcelink.html', 'searchbox.html'], + '**': ['sidebarlogo.html', 'localtoc.html', 'relations.html', + 'sourcelink.html', 'searchbox.html'] +} + +# 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/2', None)} diff --git a/docs/configuring.rst b/docs/configuring.rst new file mode 100644 index 0000000..ddba398 --- /dev/null +++ b/docs/configuring.rst @@ -0,0 +1,61 @@ +.. _configuring: + + +Configuring the NI backend +========================== + +.. note:: The NI backend requires that you install first the NI-VISA library. You can get + info here: (:ref:`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 :class:`pyvisa.highlevel.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. + +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:\\Python27\\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/hgrecco/pyvisa/issues diff --git a/docs/contributing.rst b/docs/contributing.rst new file mode 100644 index 0000000..0291f11 --- /dev/null +++ b/docs/contributing.rst @@ -0,0 +1,76 @@ +.. _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:: + + python -m visa info + +It is useful that you also provide the log output. To obtain it, add the following lines to your code:: + + import visa + visa.log_to_screen() + + +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 either clone the public repository:: + + $ git clone git://github.com/hgrecco/pyvisa.git + +Download the tarball:: + + $ curl -OL https://github.com/hgrecco/pyvisa/tarball/master + +Or, download the zipball:: + + $ curl -OL https://github.com/hgrecco/pyvisa/zipball/master + +Once you have a copy of the source, you can embed it in your Python package, or install it into your site-packages easily:: + + $ python setup.py install + + +.. note:: If you have an old system installation of Python and you don't want to + mess with it, you can try `Anaconda CE`_. 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 CE`: https://store.continuum.io/cshop/anaconda +.. _PyPI: https://pypi.python.org/pypi/PyVISA +.. _`National Instruments's VISA`: http://ni.com/visa/ +.. _github: http://github.com/hgrecco/pyvisa +.. _`issue tracker`: https://github.com/hgrecco/pyvisa/issues + + diff --git a/docs/default.css b/docs/default.css new file mode 100644 index 0000000..2cfc4c8 --- /dev/null +++ b/docs/default.css @@ -0,0 +1,255 @@ +/* +:Author: David Goodger +:Contact: goodger@users.sourceforge.net +:Date: $Date$ +:Version: $Revision$ +:Copyright: This stylesheet has been placed in the public domain. + +Default cascading style sheet for the HTML output of Docutils. +*/ + +/* "! important" is used here to override other ``margin-top`` and + ``margin-bottom`` styles that are later in the stylesheet or + more specific. See http://www.w3.org/TR/CSS1#the-cascade */ +.first { + margin-top: 0 ! important } + +.last { + margin-bottom: 0 ! important } + +.hidden { + display: none } + +a.toc-backref { + text-decoration: none ; + color: black } + +blockquote.epigraph { + margin: 2em 5em ; } + +dl.docutils dd { + margin-bottom: 0.5em } + +/* Uncomment (and remove this text!) to get bold-faced definition list terms +dl.docutils dt { + font-weight: bold } +*/ + +div.abstract { + margin: 2em 5em } + +div.abstract p.topic-title { + font-weight: bold ; + text-align: center } + +div.admonition, div.attention, div.caution, div.danger, div.error, +div.hint, div.important, div.note, div.tip, div.warning { + margin: 2em ; + border: medium outset ; + padding: 1em } + +div.admonition p.admonition-title, div.hint p.admonition-title, +div.important p.admonition-title, div.note p.admonition-title, +div.tip p.admonition-title { + font-weight: bold ; + font-family: sans-serif } + +div.attention p.admonition-title, div.caution p.admonition-title, +div.danger p.admonition-title, div.error p.admonition-title, +div.warning p.admonition-title { + color: red ; + font-weight: bold ; + font-family: sans-serif } + +/* Uncomment (and remove this text!) to get reduced vertical space in + compound paragraphs. +div.compound .compound-first, div.compound .compound-middle { + margin-bottom: 0.5em } + +div.compound .compound-last, div.compound .compound-middle { + margin-top: 0.5em } +*/ + +div.dedication { + margin: 2em 5em ; + text-align: center ; + font-style: italic } + +div.dedication p.topic-title { + font-weight: bold ; + font-style: normal } + +div.figure { + margin-left: 2em } + +div.footer, div.header { + font-size: smaller } + +div.line-block { + display: block ; + margin-top: 1em ; + margin-bottom: 1em } + +div.line-block div.line-block { + margin-top: 0 ; + margin-bottom: 0 ; + margin-left: 1.5em } + +div.sidebar { + margin-left: 1em ; + border: medium outset ; + padding: 1em ; + background-color: #ffffee ; + width: 40% ; + float: right ; + clear: right } + +div.sidebar p.rubric { + font-family: sans-serif ; + font-size: medium } + +div.system-messages { + margin: 5em } + +div.system-messages h1 { + color: red } + +div.system-message { + border: medium outset ; + padding: 1em } + +div.system-message p.system-message-title { + color: red ; + font-weight: bold } + +div.topic { + margin: 2em } + +h1.title { + text-align: center } + +h2.subtitle { + text-align: center } + +hr.docutils { + width: 75% } + +ol.simple, ul.simple { + margin-bottom: 1em } + +ol.arabic { + list-style: decimal } + +ol.loweralpha { + list-style: lower-alpha } + +ol.upperalpha { + list-style: upper-alpha } + +ol.lowerroman { + list-style: lower-roman } + +ol.upperroman { + list-style: upper-roman } + +p.attribution { + text-align: right ; + margin-left: 50% } + +p.caption { + font-style: italic } + +p.credits { + font-style: italic ; + font-size: smaller } + +p.label { + white-space: nowrap } + +p.rubric { + font-weight: bold ; + font-size: larger ; + color: maroon ; + text-align: center } + +p.sidebar-title { + font-family: sans-serif ; + font-weight: bold ; + font-size: larger } + +p.sidebar-subtitle { + font-family: sans-serif ; + font-weight: bold } + +p.topic-title { + font-weight: bold } + +pre.address { + margin-bottom: 0 ; + margin-top: 0 ; + font-family: serif ; + font-size: 100% } + +pre.line-block { + font-family: serif ; + font-size: 100% } + +pre.literal-block, pre.doctest-block { + margin-left: 2em ; + margin-right: 2em ; + background-color: #eeeeee } + +span.classifier { + font-family: sans-serif ; + font-style: oblique } + +span.classifier-delimiter { + font-family: sans-serif ; + font-weight: bold } + +span.interpreted { + font-family: sans-serif } + +span.option { + white-space: nowrap } + +span.pre { + white-space: pre } + +span.problematic { + color: red } + +table.citation { + border-left: solid thin gray } + +table.docinfo { + margin: 2em 4em } + +table.docutils { + margin-top: 0.5em ; + margin-bottom: 0.5em } + +table.footnote { + border-left: solid thin black } + +table.docutils td, table.docutils th, +table.docinfo td, table.docinfo th { + padding-left: 0.5em ; + padding-right: 0.5em ; + vertical-align: top } + +table.docutils th.field-name, table.docinfo th.docinfo-name { + font-weight: bold ; + text-align: left ; + white-space: nowrap ; + padding-left: 0 } + +h1 tt.docutils, h2 tt.docutils, h3 tt.docutils, +h4 tt.docutils, h5 tt.docutils, h6 tt.docutils { + font-size: 100% } + +tt.docutils { + background-color: #eeeeee } + +ul.auto-toc { + list-style-type: none } diff --git a/docs/example.rst b/docs/example.rst new file mode 100644 index 0000000..78fe601 --- /dev/null +++ b/docs/example.rst @@ -0,0 +1,72 @@ + + +.. _sec:more-complex-example: + +A more complex example +====================== + +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 initialise +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 initialisation 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; 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; feed:control next") + +That's it. 18 lines of lucid code. (Well, SCPI is awkward, but +that's another story.) diff --git a/docs/faq.rst b/docs/faq.rst new file mode 100644 index 0000000..b07f6d6 --- /dev/null +++ b/docs/faq.rst @@ -0,0 +1,174 @@ +.. _faq: + +Frequently asked 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 is currently maintained by Hernan E. Grecco . + +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 visa + visa.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:: + + python -m visa 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:`configuring`. + + +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:: + + python -m visa 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:`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. + + +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/hgrecco/pyvisa/blob/master/AUTHORS +.. _`Issue Tracker`: https://github.com/hgrecco/pyvisa/issues +.. _`virtual environment`: http://www.virtualenv.org/en/latest/ diff --git a/docs/getting.rst b/docs/getting.rst new file mode 100644 index 0000000..d6e85af --- /dev/null +++ b/docs/getting.rst @@ -0,0 +1,62 @@ +.. _getting: + +Installation +============ + +PyVISA is a frontend to the VISA library. It runs on Python 2.6+ and 3.2+. + +You can install it using pip_:: + + $ pip install -U pyvisa + + +NI 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:`getting_nivisa`). There are multiple +VISA implementations from different vendors. PyVISA is tested only against +`National Instruments's VISA`_. + +.. 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** + + +Testing your installation +------------------------- + + +That's all! You can check that PyVISA is correctly installed by starting up python, and creating a ResourceManager: + + >>> import visa + >>> rm = visa.ResourceManager() + >>> print(rm.list_resources()) + +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`_ + + +Using the development version +----------------------------- + +You can install the latest development version (at your own risk) directly form GitHub_:: + + $ pip install -U https://github.com/hgrecco/pyvisa/zipball/master + + +.. note:: If you have an old system installation of Python and you don't want to + mess with it, you can try `Anaconda CE`_. 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 CE`: https://store.continuum.io/cshop/anaconda +.. _PyPI: https://pypi.python.org/pypi/PyVISA +.. _GitHub: https://github.com/hgrecco/pyvisa +.. _`National Instruments's VISA`: http://ni.com/visa/ +.. _`issue tracker`: https://github.com/hgrecco/pyvisa/issues diff --git a/docs/getting_nivisa.rst b/docs/getting_nivisa.rst new file mode 100644 index 0000000..8a3c2e9 --- /dev/null +++ b/docs/getting_nivisa.rst @@ -0,0 +1,68 @@ +.. _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):: + + python -m visa info + +According to National Instruments, NI VISA **5.4.1** is available for: + +.. note:: 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 + +*Currently, only 32-bit applications are supported on the x86-64 architecture.* + +.. note:: NI-VISA runs on other linux distros but the installation is more cumbersome. + +.. _`NI-VISA for Mac OS X`: http://www.ni.com/download/ni-visa-14.0.2/5075/en/ +.. _`NI-VISA for Windows`: http://www.ni.com/download/ni-visa-5.4.1/4626/en/ +.. _`NI-VISA for Linux`: http://www.ni.com/download/ni-visa-5.4.1/4629/en/ diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..874589a --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,85 @@ +: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 visa + >>> rm = visa.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). However, you can use VISA with any language +capable of calling functions in a shared library (`.dll`, `.so`, `.dylib`). +PyVISA is Python wrapper for such shared library ... and more. + + +User guide +---------- + +.. toctree:: + :maxdepth: 1 + + getting + configuring + tutorial + rvalues + example + resources + backends + shell + architecture + +More information +---------------- + +.. toctree:: + :maxdepth: 1 + + names + migrating + contributing + faq + getting_nivisa + api/index + + +.. LocalWords: rst british reST ies vpp pyvisa docs pyvLab diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..6497cbf --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,190 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +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 diff --git a/docs/migrating.rst b/docs/migrating.rst new file mode 100644 index 0000000..761e81a --- /dev/null +++ b/docs/migrating.rst @@ -0,0 +1,294 @@ +.. _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 visa + >>> keithley = visa.instrument("GPIB::12") + >>> print(keithley.ask("*IDN?")) + +change it to: + + >>> import visa + >>> rm = visa.ResourceManager() + >>> keithley = rm.open_resource("GPIB::12") + >>> print(keithley.query("*IDN?")) + +**If you are doing:** + + >>> print(visa.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 visa + >>> rm = visa.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 = visa.VisaLibrary("/path/to/my/libvisa.so.7") + >>> lib2 = visa.VisaLibrary("/path/to/my/libvisa.so.7") + >>> lib3 = visa.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 = visa.VisaLibrary("/path/to/my/libvisa.so.7") + >>> rm = lib.resource_manager + +or equivalently: + + >>> rm = visa.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 visa + >>> rm = visa.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/ diff --git a/docs/names.rst b/docs/names.rst new file mode 100644 index 0000000..22609b8 --- /dev/null +++ b/docs/names.rst @@ -0,0 +1,157 @@ + +.. _resource_names: + +VISA resource names +=================== + +If you use the function :func:`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. +================================ ============================================= + diff --git a/docs/resources.rst b/docs/resources.rst new file mode 100644 index 0000000..93a0211 --- /dev/null +++ b/docs/resources.rst @@ -0,0 +1,166 @@ +.. _resources: + +Resources +========= + +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 +:meth:`pyvisa.highlevel.ResourceManager.open_resource` method of a :class:`pyvisa.highlevel.ResourceManager`. In general terms, there +are two main groups derived from :class:`pyvisa.resources.Resource`, :class:`pyvisa.resources.RegisterBasedResource` and :class:`pyvisa.resources.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 encounte more +often. For more information, refer to the :ref:`api`. + + +Attributes 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. + + +`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. 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. + diff --git a/docs/rvalues.rst b/docs/rvalues.rst new file mode 100644 index 0000000..383585c --- /dev/null +++ b/docs/rvalues.rst @@ -0,0 +1,181 @@ +.. _rvalues: + +Reading and Writing values +========================== + +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 two different methods for this +called :meth:`pyvisa.resources.MessageBasedResource.query_ascii_values` +and :meth:`pyvisa.resources.MessageBasedResource.query_binary_values`. +It also has the convenient :meth:`pyvisa.resources.MessageBasedResource.query_values` +which will use follow a previously established configuration. + + +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. + +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. + + +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) + + + +Preconfiguring the transfer format +---------------------------------- + +Most of the cases, each device will transfer data in the same format every time. +And making the call so detailed everytime can be annoying. For this purpose, +PyVISA provides a way to preconfigure the default. Each Message Based +Resources exposes an attribute named ``values_format`` which is an object with the following +properties: ``is_binary``, ``datatype``, ``is_big_endian``, ``container``. For example to set +e.g. little-endian doubles and a numpy array:: + + >>> inst.values_format.is_binary = True + >>> inst.values_format.datatype = 'd' + >>> inst.values_format.is_big_endian = False + >>> inst.values_format.container = numpy.array + +or shorter: + + >>> inst.values_format.use_binary('d', False, numpy.array) + +After doing this, you can simply call:: + + >>> inst.query_values('CURV?') + +which will dispatch to the appropriate function and arguments. + +If you want to default to ASCII transfer, preconfiguring is a little bit more +cumbersome as you need to specify the converters for both ways. + +For example with hex, with ``'$'`` as separator: + + >>> inst.values_format.is_binary = False + >>> inst.values_format.converter = 'x' + >>> inst.values_format.separator = '$' + >>> inst.values_format.container = numpy.array + +or shorter: + + >>> inst.values_format.use_ascii('x', '$', numpy.array) + + +This works for both query and write operations. + + +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. + + diff --git a/docs/shell.rst b/docs/shell.rst new file mode 100644 index 0000000..0943d90 --- /dev/null +++ b/docs/shell.rst @@ -0,0 +1,113 @@ +.. _shell: + +PyVISA Shell +============ + +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:: + + python -m visa 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 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. + +We can also get a list of all visa attributes:: + + +-----------------------------+------------+----------------------------+-------------------------------------+ + | 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 | + +-----------------------------+------------+----------------------------+-------------------------------------+ + +Finally, you can close the device:: + + (open) close + + +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 + diff --git a/docs/tutorial.rst b/docs/tutorial.rst new file mode 100644 index 0000000..d099d57 --- /dev/null +++ b/docs/tutorial.rst @@ -0,0 +1,91 @@ +.. _tutorial: + +Tutorial +======== + +.. note:: If you have been using PyVISA before version 1.5, you might want to + read :ref:`migrating`. + + +An example +---------- + +Let's go *in medias res* and have a look at a simple example:: + + >>> import visa + >>> rm = visa.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 ``visa``, we create a ``ResourceManager`` object. If called without +arguments, PyVISA will use the default backend (NI) which tries to find the +VISA shared library for you. You can check, the location of the shared library +used 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:`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:`resource_names`. + +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 appropiate +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()) + + +Example for serial (RS232) device +--------------------------------- + +Consider an Oxford ITC4 temperature controller, which is connected +through COM2 with my computer. The following code prints its +self-identification on the screen:: + + itc4 = rm.open_resource("COM2") + itc4.write("V") + print(itc4.read()) + +Instead of separate write and read operations, you can do both with +one ``query()`` call. Thus, the above source code is equivalent to:: + + print(itc4.query("V")) + +It couldn't be simpler. + + diff --git a/examples/itc4.py b/examples/itc4.py new file mode 100644 index 0000000..bd6e7cb --- /dev/null +++ b/examples/itc4.py @@ -0,0 +1,43 @@ +#!/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") diff --git a/examples/keithley2000.py b/examples/keithley2000.py new file mode 100644 index 0000000..aeea199 --- /dev/null +++ b/examples/keithley2000.py @@ -0,0 +1,51 @@ +#!/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") diff --git a/pyvisa/__init__.py b/pyvisa/__init__.py new file mode 100644 index 0000000..cd9d3bb --- /dev/null +++ b/pyvisa/__init__.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +""" + pyvisa + ~~~~~~ + + Python wrapper of National Instrument (NI) Virtual Instruments Software + Architecture library (VISA). + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import logging +import pkg_resources + +from . import compat +logger = logging.getLogger('pyvisa') +logger.addHandler(compat.NullHandler()) + + +def log_to_screen(level=logging.DEBUG): + logger.setLevel(level) + ch = logging.StreamHandler() + ch.setLevel(level) + + formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + + ch.setFormatter(formatter) + + logger.addHandler(ch) + + +__version__ = "unknown" +try: # pragma: no cover + __version__ = pkg_resources.get_distribution('pyvisa').version +except: # pragma: no cover + pass # we seem to have a local copy without any repository control or installed without setuptools + # so the reported version will be __unknown__ + + +from .highlevel import ResourceManager +from .errors import (Error, VisaIOError, VisaIOWarning, VisaTypeError, + UnknownHandler, OSNotSupported, InvalidBinaryFormat, + InvalidSession, LibraryError) +# This is needed to registry all resources. +from .resources import Resource +from . import ctwrapper diff --git a/pyvisa/attributes.py b/pyvisa/attributes.py new file mode 100644 index 0000000..80f8b9b --- /dev/null +++ b/pyvisa/attributes.py @@ -0,0 +1,3289 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.attributes + ~~~~~~~~~~~~~~~~~ + + Comprehensive of all properties. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +from collections import defaultdict + +from .compat import with_metaclass +from . import constants + +#: Not available value. +NotAvailable = object() + +#: Attribute for all session types. +AllSessionTypes = object() + + +#: Map resource to attribute +AttributesPerResource = defaultdict(set) +AttributesByID = dict() + + +class AttributeType(type): + """Base Type for Attributes + + Assigns the `attribute_id` and improves the documentation. + """ + + def __init__(cls, name, bases, dct): + super(AttributeType, cls).__init__(name, bases, dct) + if not name.startswith('AttrVI_'): + return + cls.attribute_id = getattr(constants, cls.visa_name) + 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 + + +class Attribute(with_metaclass(AttributeType)): + """Base class for Attributes to be used as Properties. + """ + + #: List of resource types with this attribute. + #: each element is a tuple (constants.InterfaceType, str) + resources = [] + + #: Name of the Python property to be matched to this attribute. + py_name = 'To be specified' + + #: Name of the VISA Attribute + visa_name = 'To be specified' + + #: Numeric constant of the VISA Attribute + attribute_id = 0 + + #: Default value fo the VISA Attribute + default = 'N/A' + + #: Access + read, write, local = False, False, False + + @classmethod + def redoc(cls): + cls.__doc__ += '\n:VISA Attribute: %s (%s)' % (cls.visa_name, + cls.attribute_id) + + def post_get(self, value): + """Override this method to check or modify the value returned by the VISA function. + + :param value: the value returned by the VISA library. + :return: the equivalent python value. + """ + return value + + def pre_set(self, value): + """Override this method to check or modify the value to be passed to the VISA function. + + :param value: the python value to be passed to VISA library. + :return: the equivalent value. + """ + return value + + def __get__(self, instance, owner): + 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, value): + if not self.write: + raise AttributeError("can't write attribute") + + instance.set_visa_attribute(self.attribute_id, self.pre_set(value)) + + @classmethod + def in_resource(cls, session_type): + """Returns True if the attribute is part of a given session type. + + The session_type is a tuple with the interface type and resource_class + + :type session_type: (constants.InterfaceType, str) + :rtype: bool + """ + if cls.resources is AllSessionTypes: + return True + return session_type in cls.resources + + +class EnumAttribute(Attribute): + """Class for attributes with values that map to a PyVISA Enum. + """ + + #: Enum type with valid values. + enum_type = None + + @classmethod + def redoc(cls): + super(EnumAttribute, cls).redoc() + cls.__doc__ += '\n:type: :class:%s.%s' % (cls.enum_type.__module__, + cls.enum_type.__name__) + + def post_get(self, value): + return self.enum_type(value) + + def pre_set(self, value): + if value not in self.enum_type: + 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): + super(IntAttribute, cls).redoc() + cls.__doc__ += '\n:type: int' + + def post_get(self, value): + 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, max_value, values = None, None, [] + + @classmethod + def redoc(cls): + 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): + 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 = [] + + @classmethod + def redoc(cls): + super(ValuesAttribute, cls).redoc() + cls.__doc__ += '\n:values: %s' % cls.values + + def pre_set(self, value): + 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. + """ + + @classmethod + def redoc(cls): + super(BooleanAttribute, cls).redoc() + cls.__doc__ += '\n:type: bool' + + def post_get(self, value): + return value == constants.VI_TRUE + + def pre_set(self, value): + return constants.VI_TRUE if value else constants.VI_FALSE + + +class CharAttribute(Attribute): + """Class for attributes with char values. + """ + + @classmethod + def redoc(cls): + super(CharAttribute, cls).redoc() + cls.__doc__ += '\n:range: 0 <= x <= 255\n:type: int' + + def post_get(self, value): + return chr(value) + + def pre_set(self, value): + return ord(value) + + +# noinspection PyPep8Naming +class AttrVI_ATTR_4882_COMPLIANT(BooleanAttribute): + """VI_ATTR_4882_COMPLIANT specifies 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_ALLOW_TRANSMIT(BooleanAttribute): + """If set to VI_FALSE, it suspends transmission as if an XOFF character + has been received. If set to VI_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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_AVAIL_NUM(RangeAttribute): + """VI_ATTR_ASRL_AVAIL_NUM shows the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_BAUD(RangeAttribute): + """VI_ATTR_ASRL_BAUD is the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_BREAK_LEN(RangeAttribute): + """This controls the duration (in milliseconds) of the break signal + asserted when VI_ATTR_ASRL_END_OUT is set to VI_ASRL_END_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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_BREAK_STATE(EnumAttribute): + """If set to VI_STATE_ASSERTED, it suspends character transmission and + places the transmission line in a break state until this attribute + is reset to VI_STATE_UNASSERTED. This attribute lets you manually + control the assertion state and length of a break signal. 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_CONNECTED(BooleanAttribute): + """VI_ATTR_ASRL_CONNECTED indicates 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_CTS_STATE(EnumAttribute): + """VI_ATTR_ASRL_CTS_STATE shows the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_DATA_BITS(RangeAttribute): + """VI_ATTR_ASRL_DATA_BITS is the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_DCD_STATE(EnumAttribute): + """VI_ATTR_ASRL_DCD_STATE represents the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_DISCARD_NULL(BooleanAttribute): + """If set to VI_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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_DSR_STATE(EnumAttribute): + """VI_ATTR_ASRL_DSR_STATE shows the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_DTR_STATE(EnumAttribute): + """VI_ATTR_ASRL_DTR_STATE shows the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_END_IN(EnumAttribute): + """VI_ATTR_ASRL_END_IN indicates the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_END_OUT(EnumAttribute): + """VI_ATTR_ASRL_END_OUT indicates the method used to terminate write + operations. + """ + resources = [(constants.InterfaceType.asrl, 'INSTR')] + + py_name = '' + + visa_name = 'VI_ATTR_ASRL_END_OUT' + + visa_type = 'ViUInt16' + + default = constants.SerialTermination.none + + read, write, local = True, True, True + + enum_type = constants.SerialTermination + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_FLOW_CNTRL(RangeAttribute): + """VI_ATTR_ASRL_FLOW_CNTRL indicates 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 + + min_value, max_value, values = 0, 65535, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_PARITY(EnumAttribute): + """VI_ATTR_ASRL_PARITY is the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_REPLACE_CHAR(RangeAttribute): + """VI_ATTR_ASRL_REPLACE_CHAR specifies the character to be used to + replace incoming characters that arrive with errors (such as + 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 + + min_value, max_value, values = 0, 0xFF, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_RI_STATE(EnumAttribute): + """VI_ATTR_ASRL_RI_STATE represents the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_RTS_STATE(EnumAttribute): + """VI_ATTR_ASRL_RTS_STATE is used to 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_STOP_BITS(EnumAttribute): + """VI_ATTR_ASRL_STOP_BITS is the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_WIRE_MODE(RangeAttribute): + """ + + """ + 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 + + min_value, max_value, values = -32768, 32767, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_XOFF_CHAR(RangeAttribute): + """VI_ATTR_ASRL_XOFF_CHAR specifies the value of the 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 + + min_value, max_value, values = 0, 0xFF, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_XON_CHAR(RangeAttribute): + """VI_ATTR_ASRL_XON_CHAR specifies the value of the 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 + + min_value, max_value, values = 0, 0xFF, [] + + +# Could not generate class for VI_ATTR_BUFFER.html +# Exception: +""" +'list' object has no attribute 'startswith' +""" + + +# noinspection PyPep8Naming +class AttrVI_ATTR_CMDR_LA(RangeAttribute): + """VI_ATTR_CMDR_LA is the unique logical address of the commander of the + VXI device used by the given session. + """ + 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] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_DEST_ACCESS_PRIV(RangeAttribute): + """VI_ATTR_DEST_ACCESS_PRIV specifies the address modifier to be used in + high-level access operations, such as viOutXX() and viMoveOutXX(), + when writing to the destination. + """ + 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_DEST_BYTE_ORDER(RangeAttribute): + """VI_ATTR_DEST_BYTE_ORDER specifies the byte order to be used in high- + level access operations, such as viOutXX() and viMoveOutXX(), when + writing to the destination. + """ + 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 + + min_value, max_value, values = 0, 65535, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_DEST_INCREMENT(RangeAttribute): + """VI_ATTR_DEST_INCREMENT is used in the viMoveOutXX() operations to + specify by how many elements the destination offset is to be + incremented after every 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_DEV_STATUS_BYTE(RangeAttribute): + """This attribute specifies the 488-style status byte of the local + controller or device associated with 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 + + min_value, max_value, values = 0, 0xFF, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_DMA_ALLOW_EN(BooleanAttribute): + """This attribute specifies whether I/O accesses should use DMA (VI_TRUE) + or Programmed I/O (VI_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. + """ + resources = [(constants.InterfaceType.gpib, 'INSTR'), + (constants.InterfaceType.gpib, 'INTFC'), + (constants.InterfaceType.pxi, 'INSTR'), + (constants.InterfaceType.asrl, 'INSTR'), + (constants.InterfaceType.tcpip, 'INSTR'), + (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 + + +# Could not generate class for VI_ATTR_EVENT_TYPE.html +# Exception: +""" +Unknown type: ViEventType. Range: [u'0h to FFFFFFFFh'] +""" + + +# noinspection PyPep8Naming +class AttrVI_ATTR_FDC_CHNL(RangeAttribute): + """VI_ATTR_FDC_CHNL determines which Fast Data Channel (FDC) will be used + 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_FDC_MODE(RangeAttribute): + """VI_ATTR_FDC_MODE specifies 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_FDC_USE_PAIR(BooleanAttribute): + """Setting VI_ATTR_FDC_USE_PAIR to VI_TRUE specifies to use a channel + pair for transferring data. Otherwise, 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_FILE_APPEND_EN(BooleanAttribute): + """This attribute specifies whether viReadToFile() will 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_ADDR_STATE(EnumAttribute): + """This attribute shows whether the specified GPIB interface is currently + addressed to talk or listen, or is 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_ATN_STATE(EnumAttribute): + """This attribute shows the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_CIC_STATE(BooleanAttribute): + """This attribute shows whether the specified GPIB interface is 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_HS488_CBL_LEN(RangeAttribute): + """This attribute specifies the 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 = -32768, 32767, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_NDAC_STATE(EnumAttribute): + """This attribute shows the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_PRIMARY_ADDR(RangeAttribute): + """VI_ATTR_GPIB_PRIMARY_ADDR specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_READDR_EN(BooleanAttribute): + """VI_ATTR_GPIB_READDR_EN specifies whether to use repeat addressing + before each read or 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_REN_STATE(EnumAttribute): + """VI_ATTR_GPIB_REN_STATE returns the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_SECONDARY_ADDR(RangeAttribute): + """VI_ATTR_GPIB_SECONDARY_ADDR specifies the 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] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_SRQ_STATE(EnumAttribute): + """This attribute shows the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_SYS_CNTRL_STATE(BooleanAttribute): + """This attribute shows whether the specified GPIB interface is 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_UNADDR_EN(BooleanAttribute): + """VI_ATTR_GPIB_UNADDR_EN specifies whether to unaddress the device (UNT + and UNL) after each read or 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_IMMEDIATE_SERV(BooleanAttribute): + """VI_ATTR_IMMEDIATE_SERV specifies whether the device associated with + this session is 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_INTF_INST_NAME(Attribute): + """VI_ATTR_INTF_INST_NAME specifies 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 + + # [u'N/A'] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_INTF_NUM(RangeAttribute): + """VI_ATTR_INTF_NUM specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_INTF_TYPE(RangeAttribute): + """VI_ATTR_INTF_TYPE specifies the interface type of the given session. + """ + resources = AllSessionTypes + + py_name = '' + + visa_name = 'VI_ATTR_INTF_TYPE' + + visa_type = 'ViUInt16' + + default = NotAvailable + + read, write, local = True, False, False + + min_value, max_value, values = 0, 65535, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_IO_PROT(RangeAttribute): + """VI_ATTR_IO_PROT specifies which 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. + """ + resources = [(constants.InterfaceType.gpib, 'INTFC'), + (constants.InterfaceType.gpib, 'INSTR'), + (constants.InterfaceType.asrl, '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.VI_PROT_NORMAL + + read, write, local = True, True, True + + min_value, max_value, values = 0, 65535, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_MAINFRAME_LA(RangeAttribute): + """VI_ATTR_MA.infRAME_LA specifies the 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] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_MANF_ID(RangeAttribute): + """VI_ATTR_MANF_ID is the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_MANF_NAME(Attribute): + """This string attribute is the 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 + + # [u'N/A'] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_MAX_QUEUE_LENGTH(RangeAttribute): + """VI_ATTR_MAX_QUEUE_LENGTH specifies the 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, [] + + +# Could not generate class for VI_ATTR_MEM_BASE.html +# Exception: +""" +Unknown type: VI_ATTR_MEM_BASE: +ViBusAddress +VI_ATTR_MEM_BASE_32: +ViUInt32 +VI_ATTR_MEM_BASE_64: +ViUInt64. Range: [u'VI_ATTR_MEM_BASE:', u'0h to FFFFFFFFh for 32\u2011bit applications', u'0h to FFFFFFFFFFFFFFFFh for 64\u2011bit applications', u'VI_ATTR_MEM_BASE_32:', u'0h to FFFFFFFFh', u'VI_ATTR_MEM_BASE_64:', u'0h to FFFFFFFFFFFFFFFFh'] +""" + + +# Could not generate class for VI_ATTR_MEM_SIZE.html +# Exception: +""" +Unknown type: VI_ATTR_MEM_SIZE: +ViBusSize +VI_ATTR_MEM_SIZE_32: +ViUInt32 +VI_ATTR_MEM_SIZE_64: +ViUInt64. Range: [u'VI_ATTR_MEM_SIZE:', u'0h to FFFFFFFFh for 32\u2011bit applications', u'0h to FFFFFFFFFFFFFFFFh for 64\u2011bit applications', u'VI_ATTR_MEM_SIZE_32:', u'0h to FFFFFFFFh', u'VI_ATTR_MEM_SIZE_64:', u'0h to FFFFFFFFFFFFFFFFh'] +""" + + +# noinspection PyPep8Naming +class AttrVI_ATTR_MEM_SPACE(RangeAttribute): + """VI_ATTR_MEM_SPACE specifies the VXIbus address space used by the + device. The three types are A16, A24, or A32 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 + + min_value, max_value, values = 0, 65535, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_MODEL_CODE(RangeAttribute): + """VI_ATTR_MODEL_CODE specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_MODEL_NAME(Attribute): + """This string attribute is the 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 + + # [u'N/A'] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_ACTUAL_LWIDTH(ValuesAttribute): + """VI_ATTR_PXI_ACTUAL_LWIDTH specifies the PCI Express link width + negotiated between the PCI Express 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] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_BUS_NUM(RangeAttribute): + """VI_ATTR_PXI_BUS_NUM specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_CHASSIS(RangeAttribute): + """VI_ATTR_PXI_CHASSIS specifies the 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] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_DEST_TRIG_BUS(RangeAttribute): + """VI_ATTR_PXI_DEST_TRIG_BUS specifies 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 = -32768, 32767, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_DEV_NUM(RangeAttribute): + """This is the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_DSTAR_BUS(RangeAttribute): + """VI_ATTR_PXI_DSTAR_BUS specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_DSTAR_SET(RangeAttribute): + """ + + """ + 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] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_FUNC_NUM(RangeAttribute): + """This is the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_IS_EXPRESS(BooleanAttribute): + """VI_ATTR_PXI_IS_EXPRESS specifies 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_MAX_LWIDTH(ValuesAttribute): + """VI_ATTR_PXI_MAX_LWIDTH specifies the 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] + + +# noinspection PyPep8Naming +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 VI_PXI_ADDR_NONE, + the value of this attribute is meaningless for the given PXI + device. + """ + resources = [(constants.InterfaceType.pxi, 'INSTR')] + + py_name = '' + + visa_name = 'VI_ATTR_PXI_MEM_BASE_BARX' + + visa_type = 'ViUInt32' + + default = NotAvailable + + read, write, local = True, False, False + + min_value, max_value, values = 0, 0xFFFFFFFF, [] + + +# noinspection PyPep8Naming +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 VI_PXI_ADDR_NONE, + the value of this attribute is meaningless for the given PXI + device. + """ + resources = [(constants.InterfaceType.pxi, 'INSTR')] + + py_name = '' + + visa_name = 'VI_ATTR_PXI_MEM_SIZE_BARX' + + visa_type = 'ViUInt32' + + default = NotAvailable + + read, write, local = True, False, False + + min_value, max_value, values = 0, 0xFFFFFFFF, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_MEM_TYPE_BARX(RangeAttribute): + """Memory type used by the device in the specified BAR (if applicable). + """ + resources = [(constants.InterfaceType.pxi, 'INSTR')] + + py_name = '' + + visa_name = 'VI_ATTR_PXI_MEM_TYPE_BARX' + + visa_type = 'ViUInt16' + + default = NotAvailable + + read, write, local = True, False, False + + min_value, max_value, values = 0, 65535, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_SLOT_LBUS_LEFT(RangeAttribute): + """VI_ATTR_PXI_SLOT_LBUS_LEFT specifies the slot number or special + feature connected to the local bus left lines of this device. + """ + 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] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_SLOT_LBUS_RIGHT(RangeAttribute): + """VI_ATTR_PXI_SLOT_LBUS_RIGHT specifies the slot number or special + feature connected to the local bus right lines of this device. + """ + 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] + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_SLOT_LWIDTH(ValuesAttribute): + """VI_ATTR_PXI_SLOT_LWIDTH specifies the PCI Express link width of the + PXI Express peripheral slot in which the device resides. 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] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_SLOTPATH(Attribute): + """VI_ATTR_PXI_SLOTPATH specifies the 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 + + # [u'N/A'] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_SRC_TRIG_BUS(RangeAttribute): + """VI_ATTR_PXI_SRC_TRIG_BUS specifies the 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 = -32768, 32767, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_STAR_TRIG_BUS(RangeAttribute): + """VI_ATTR_PXI_STAR_TRIG_BUS specifies 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 = -32768, 32767, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_STAR_TRIG_LINE(RangeAttribute): + """VI_ATTR_PXI_STAR_TRIG_LINE specifies 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 = -32768, 32767, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_TRIG_BUS(RangeAttribute): + """VI_ATTR_PXI_TRIG_BUS specifies 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 = -32768, 32767, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_RD_BUF_OPER_MODE(RangeAttribute): + """VI_ATTR_RD_BUF_OPER_MODE specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_RD_BUF_SIZE(RangeAttribute): + """This is the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_RM_SESSION(RangeAttribute): + """This is the current size of the formatted I/O input buffer for this + session. The user can modify this value by calling viSetBuf(). + + Not implemented as resource property, use .resource_manager.session + """ + resources = AllSessionTypes + + # See docstring + py_name = '' + + visa_name = 'VI_ATTR_RM_SESSION' + + visa_type = 'ViUInt32' + + default = NotAvailable + + read, write, local = True, False, True + + min_value, max_value, values = 0, 4294967295, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_RSRC_CLASS(Attribute): + """VI_ATTR_RSRC_CLASS specifies the resource class (for example, "INSTR") + as defined by the canonical resource name. + """ + resources = AllSessionTypes + + py_name = 'resource_class' + + visa_name = 'VI_ATTR_RSRC_CLASS' + + visa_type = 'ViString' + + default = NotAvailable + + read, write, local = True, False, False + + # [u'N/A'] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_RSRC_IMPL_VERSION(RangeAttribute): + """VI_ATTR_RSRC_IMPL_VERSION is the resource version that uniquely identifies + each of the different 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_RSRC_LOCK_STATE(EnumAttribute): + """VI_ATTR_RSRC_LOCK_STATE indicates the 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.VI_NO_LOCK + + read, write, local = True, False, False + + enum_type = constants.AccessModes + + +# noinspection PyPep8Naming +class AttrVI_ATTR_RSRC_MANF_ID(RangeAttribute): + """VI_ATTR_RSRC_MANF_ID is a value that corresponds to the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_RSRC_MANF_NAME(Attribute): + """VI_ATTR_RSRC_MANF_NAME is a string that corresponds to the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_RSRC_NAME(Attribute): + """VI_ATTR_RSRC_MANF_NAME is a string that corresponds to the 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_name' + + visa_name = 'VI_ATTR_RSRC_NAME' + + visa_type = 'ViRsrc' + + default = NotAvailable + + read, write, local = True, False, False + + +# noinspection PyPep8Naming +class AttrVI_ATTR_RSRC_SPEC_VERSION(RangeAttribute): + """VI_ATTR_RSRC_SPEC_VERSION is the resource version that uniquely identifies + the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_SEND_END_EN(BooleanAttribute): + """VI_ATTR_SEND_END_EN specifies whether to assert END during the + transfer of the last byte of the buffer. + """ + resources = [(constants.InterfaceType.gpib, 'INSTR'), + (constants.InterfaceType.gpib, 'INTFC'), + (constants.InterfaceType.asrl, 'INSTR'), + (constants.InterfaceType.tcpip, 'INSTR'), + (constants.InterfaceType.usb, 'INSTR'), + (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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_SLOT(RangeAttribute): + """VI_ATTR_SLOT specifies the physical slot location of the device. If + the slot number is not known, VI_UNKNOWN_SLOT is returned. + """ + 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 + + # [u'VXI', u'0 to 12', u'VI_UNKNOWN_SLOT (\u20131)', u'PXI', u'1 to 18', u'VI_UNKNOWN_SLOT (\u20131)'], ValueError('too many values to unpack',) + + +# noinspection PyPep8Naming +class AttrVI_ATTR_SRC_ACCESS_PRIV(RangeAttribute): + """VI_ATTR_SRC_ACCESS_PRIV specifies the address modifier to be used in + high-level access operations, such as viInXX() and viMoveInXX(), + when reading from the source. + """ + 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 + + min_value, max_value, values = 0, 65535, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_SRC_BYTE_ORDER(RangeAttribute): + """VI_ATTR_SRC_BYTE_ORDER specifies the byte order to be used in high- + level access operations, such as viInXX() and viMoveInXX(), when + reading from the source. + """ + 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 + + min_value, max_value, values = 0, 65535, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_SRC_INCREMENT(RangeAttribute): + """VI_ATTR_SRC_INCREMENT is used in the viMoveInXX() operations to + specify by how many elements the source offset is to be + incremented after every 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_SUPPRESS_END_EN(BooleanAttribute): + """VI_ATTR_SUPPRESS_END_EN is relevant only in viRead and related + operations. + """ + resources = [(constants.InterfaceType.asrl, 'INSTR'), + (constants.InterfaceType.tcpip, 'SOCKET'), + (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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_TCPIP_ADDR(Attribute): + """This is the 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 + + # [u'N/A'] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_TCPIP_DEVICE_NAME(Attribute): + """This specifies the 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 + + # [u'N/A'] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_TCPIP_HOSTNAME(Attribute): + """This specifies the 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 + + # [u'N/A'] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_TCPIP_KEEPALIVE(BooleanAttribute): + """Setting this attribute to TRUE requests that a TCP/IP provider enable + the use of keep-alive packets on TCP connections. 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 + + +# noinspection PyPep8Naming +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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_TCPIP_PORT(RangeAttribute): + """This specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_TERMCHAR(RangeAttribute): + """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. + """ + 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 + + min_value, max_value, values = 0, 0xFF, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_TERMCHAR_EN(BooleanAttribute): + """VI_ATTR_TERMCHAR_EN is a flag that determines whether the read + operation should 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). + """ + 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_TMO_VALUE(RangeAttribute): + """VI_ATTR_TMO_VALUE specifies the minimum timeout value to use (in + milliseconds) when accessing the device associated with the given + session. 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 = '' + + visa_name = 'VI_ATTR_TMO_VALUE' + + visa_type = 'ViUInt32' + + default = 2000 + + read, write, local = True, True, True + + min_value, max_value, values = 0, 0xFFFFFFFF, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_TRIG_ID(ValuesAttribute): + """VI_ATTR_TRIG_ID is the 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 + + values = [] #TODO + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_ALT_SETTING(RangeAttribute): + """VI_ATTR_USB_ALT_SETTING specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_BULK_IN_PIPE(RangeAttribute): + """VI_ATTR_USB_BULK_IN_PIPE specifies the 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] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_BULK_IN_STATUS(RangeAttribute): + """VI_ATTR_USB_BULK_IN_STATUS specifies whether 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_BULK_OUT_PIPE(RangeAttribute): + """VI_ATTR_USB_BULK_OUT_PIPE specifies the endpoint address of the USB + bulk-out or interrupt-out pipe used by the given session. 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] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_BULK_OUT_STATUS(RangeAttribute): + """VI_ATTR_USB_BULK_OUT_STATUS specifies whether the USB bulk-out or + interrupt-out 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_OUT_STATUS' + + visa_type = 'ViInt16' + + default = NotAvailable + + read, write, local = True, True, True + + min_value, max_value, values = -32768, 32767, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_CLASS(RangeAttribute): + """VI_ATTR_USB_CLASS specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_CTRL_PIPE(RangeAttribute): + """VI_ATTR_USB_CTRL_PIPE specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_END_IN(ValuesAttribute): + """VI_ATTR_USB_END_IN indicates the 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 + + values = [constants.VI_USB_END_NONE, + constants.VI_USB_END_SHORT, + constants.VI_USB_END_SHORT_OR_COUNT] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_INTFC_NUM(RangeAttribute): + """VI_ATTR_USB_INTFC_NUM specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_INTR_IN_PIPE(RangeAttribute): + """VI_ATTR_USB_INTR_IN_PIPE specifies the 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] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_INTR_IN_STATUS(RangeAttribute): + """VI_ATTR_USB_INTR_IN_STATUS specifies 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_MAX_INTR_SIZE(RangeAttribute): + """VI_ATTR_USB_MAX_INTR_SIZE specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_NUM_INTFCS(RangeAttribute): + """VI_ATTR_USB_NUM_INTFCS specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_NUM_PIPES(RangeAttribute): + """VI_ATTR_USB_NUM_PIPES specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_PROTOCOL(RangeAttribute): + """VI_ATTR_USB_PROTOCOL specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_SERIAL_NUM(Attribute): + """VI_ATTR_USB_SERIAL_NUM specifies the 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 + + # [u'N/A'] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_SUBCLASS(RangeAttribute): + """VI_ATTR_USB_SUBCLASS specifies the 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, [] + + +# Could not generate class for VI_ATTR_USER_DATA.html +# Exception: +""" +Unknown type: VI_ATTR_USER_DATA: +ViAddr +VI_ATTR_USER_DATA_32: +ViUInt32 +VI_ATTR_USER_DATA_64: +ViUInt64. Range: [u'VI_ATTR_USER_DATA:', u'Not specified', u'VI_ATTR_USER_DATA_32:', u'0h to FFFFFFFFh', u'VI_ATTR_USER_DATA_64:', u'0h to FFFFFFFFFFFFFFFFh'] +""" + + +# noinspection PyPep8Naming +class AttrVI_ATTR_VXI_DEV_CLASS(RangeAttribute): + """This attribute represents the VXI-defined device class to which the + resource belongs, either message based (VI_VXI_CLASS_MESSAGE), + register based (VI_VXI_CLASS_REGISTER), extended + (VI_VXI_CLASS_EXTENDED), or memory (VI_VXI_CLASS_MEMORY). 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 + + min_value, max_value, values = 0, 65535, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_VXI_LA(RangeAttribute): + """For an INSTR session, VI_ATTR_VXI_LA specifies the logical address of + the VXI or VME device used by the given session. 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_VXI_TRIG_DIR(RangeAttribute): + """VI_ATTR_TRIG_DIR is a 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_VXI_TRIG_LINES_EN(RangeAttribute): + """VI_ATTR_VXI_TRIG_LINES_EN is a 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_VXI_TRIG_STATUS(RangeAttribute): + """This attribute shows the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_VXI_TRIG_SUPPORT(RangeAttribute): + """This attribute shows which VXI trigger lines this implementation + supports. This is a bit vector with bits 0-9 corresponding to + VI_TRIG_TTL0 through VI_TRIG_ECL1. + """ + 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_VXI_VME_INTR_STATUS(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_VXI_VME_INTR_STATUS' + + visa_type = 'ViUInt16' + + default = NotAvailable + + read, write, local = True, False, False + + min_value, max_value, values = 0, 65535, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_VXI_VME_SYSFAIL_STATE(EnumAttribute): + """This attribute shows the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_WIN_ACCESS(RangeAttribute): + """VI_ATTR_WIN_ACCESS specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_WIN_ACCESS_PRIV(RangeAttribute): + """VI_ATTR_WIN_ACCESS_PRIV specifies the address modifier to be used in + low-level access operations, such as 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 + + min_value, max_value, values = 0, 65535, [] + + +# Could not generate class for VI_ATTR_WIN_BASE_ADDR.html +# Exception: +""" +Unknown type: VI_ATTR_WIN_BASE_ADDR: +ViBusAddress +VI_ATTR_WIN_BASE_ADDR_32: +ViUInt32 +VI_ATTR_WIN_BASE_ADDR_64: +ViUInt64. Range: [u'VI_ATTR_WIN_BASE_ADDR:', u'0h to FFFFFFFFh for 32\u2011bit applications', u'0h to FFFFFFFFFFFFFFFFh for 64\u2011bit applications', u'VI_ATTR_WIN_BASE_ADDR_32:', u'0h to FFFFFFFFh', u'VI_ATTR_WIN_BASE_ADDR_64:', u'0h to FFFFFFFFFFFFFFFFh'] +""" + + +# noinspection PyPep8Naming +class AttrVI_ATTR_WIN_BYTE_ORDER(RangeAttribute): + """VI_ATTR_WIN_BYTE_ORDER specifies the byte order to be used in low- + level access operations, such as 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 + + min_value, max_value, values = 0, 65535, [] + + +# Could not generate class for VI_ATTR_WIN_SIZE.html +# Exception: +""" +Unknown type: VI_ATTR_WIN_SIZE: +ViBusSize +VI_ATTR_WIN_SIZE_32: +ViUInt32 +VI_ATTR_WIN_SIZE_64: +ViUInt64. Range: [u'VI_ATTR_WIN_SIZE:', u'0h to FFFFFFFFh for 32\u2011bit applications', u'0h to FFFFFFFFFFFFFFFFh for 64\u2011bit applications', u'VI_ATTR_WIN_SIZE_32:', u'0h to FFFFFFFFh', u'VI_ATTR_WIN_SIZE_64:', u'0h to FFFFFFFFFFFFFFFFh'] +""" + + +# noinspection PyPep8Naming +class AttrVI_ATTR_WR_BUF_OPER_MODE(RangeAttribute): + """VI_ATTR_WR_BUF_OPER_MODE specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_WR_BUF_SIZE(RangeAttribute): + """This is the 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, [] + diff --git a/pyvisa/compat/__init__.py b/pyvisa/compat/__init__.py new file mode 100644 index 0000000..a3dc8fb --- /dev/null +++ b/pyvisa/compat/__init__.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.compat + ~~~~~~~~~~~~~ + + Compatibility layer. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import sys +PYTHON3 = sys.version >= '3' + +if PYTHON3: + string_types = str + + def u(x): + return x + + integer_types = (int, ) + + input = input +else: + string_types = basestring + + import codecs + + def u(x): + return codecs.unicode_escape_decode(x)[0] + + integer_types = (int, long) + + input = raw_input + +if sys.version_info < (2, 7): + try: + # noinspection PyPackageRequirements + import unittest2 as unittest + except ImportError: + raise Exception("Testing PyVISA in Python 2.6 requires package 'unittest2'") +else: + import unittest + +try: + from collections import OrderedDict +except ImportError: + from .ordereddict import OrderedDict + +try: + from logging import NullHandler +except ImportError: + from .nullhandler import NullHandler + +try: + from subprocess import check_output +except ImportError: + from .check_output import check_output + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(meta): + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, str('temporary_class'), (), {}) diff --git a/pyvisa/compat/check_output.py b/pyvisa/compat/check_output.py new file mode 100644 index 0000000..4d57e8b --- /dev/null +++ b/pyvisa/compat/check_output.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.compat.check_output + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Taken from the Python 2.7 source code. + + :copyright: 2013, PSF + :license: PSF License +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import subprocess + + +def check_output(*popenargs, **kwargs): + r"""Run command with arguments and return its output as a byte string. + + Backported from Python 2.7 as it's implemented as pure python on stdlib. + + >>> check_output(['/usr/bin/python', '--version']) + Python 2.6.2 + """ + process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs) + output, unused_err = process.communicate() + retcode = process.poll() + if retcode: + cmd = kwargs.get("args") + if cmd is None: + cmd = popenargs[0] + error = subprocess.CalledProcessError(retcode, cmd) + error.output = output + raise error + return output diff --git a/pyvisa/compat/nullhandler.py b/pyvisa/compat/nullhandler.py new file mode 100644 index 0000000..e1ff509 --- /dev/null +++ b/pyvisa/compat/nullhandler.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.compat.nullhandler + ~~~~~~~~~~~~~~~~~~~~~~~~~ + + Taken from the Python 2.7 source code. + + :copyright: 2013, PSF + :license: PSF License +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import logging + + +class NullHandler(logging.Handler): + """ + This handler does nothing. It's intended to be used to avoid the + "No handlers could be found for logger XXX" one-off warning. This is + important for library code, which may contain code to log events. If a user + of the library does not configure logging, the one-off warning might be + produced; to avoid this, the library developer simply needs to instantiate + a NullHandler and add it to the top-level logger of the library module or + package. + """ + def handle(self, record): + pass + + def emit(self, record): + pass + + def createLock(self): + # noinspection PyAttributeOutsideInit + self.lock = None diff --git a/pyvisa/compat/ordereddict.py b/pyvisa/compat/ordereddict.py new file mode 100644 index 0000000..5b0303f --- /dev/null +++ b/pyvisa/compat/ordereddict.py @@ -0,0 +1,127 @@ +# Copyright (c) 2009 Raymond Hettinger +# +# 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 UserDict import DictMixin + +class OrderedDict(dict, DictMixin): + + def __init__(self, *args, **kwds): + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + try: + self.__end + except AttributeError: + self.clear() + self.update(*args, **kwds) + + def clear(self): + self.__end = end = [] + end += [None, end, end] # sentinel node for doubly linked list + self.__map = {} # key --> [key, prev, next] + dict.clear(self) + + def __setitem__(self, key, value): + if key not in self: + end = self.__end + curr = end[1] + curr[2] = end[1] = self.__map[key] = [key, curr, end] + dict.__setitem__(self, key, value) + + def __delitem__(self, key): + dict.__delitem__(self, key) + key, prev, next = self.__map.pop(key) + prev[2] = next + next[1] = prev + + def __iter__(self): + end = self.__end + curr = end[2] + while curr is not end: + yield curr[0] + curr = curr[2] + + def __reversed__(self): + end = self.__end + curr = end[1] + while curr is not end: + yield curr[0] + curr = curr[1] + + def popitem(self, last=True): + if not self: + raise KeyError('dictionary is empty') + if last: + key = reversed(self).next() + else: + key = iter(self).next() + value = self.pop(key) + return key, value + + def __reduce__(self): + items = [[k, self[k]] for k in self] + tmp = self.__map, self.__end + del self.__map, self.__end + inst_dict = vars(self).copy() + self.__map, self.__end = tmp + if inst_dict: + return (self.__class__, (items,), inst_dict) + return self.__class__, (items,) + + def keys(self): + return list(self) + + setdefault = DictMixin.setdefault + update = DictMixin.update + pop = DictMixin.pop + values = DictMixin.values + items = DictMixin.items + iterkeys = DictMixin.iterkeys + itervalues = DictMixin.itervalues + iteritems = DictMixin.iteritems + + def __repr__(self): + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, self.items()) + + def copy(self): + return self.__class__(self) + + @classmethod + def fromkeys(cls, iterable, value=None): + d = cls() + for key in iterable: + d[key] = value + return d + + def __eq__(self, other): + if isinstance(other, OrderedDict): + if len(self) != len(other): + return False + for p, q in zip(self.items(), other.items()): + if p != q: + return False + return True + return dict.__eq__(self, other) + + def __ne__(self, other): + return not self == other diff --git a/pyvisa/compat/struct.py b/pyvisa/compat/struct.py new file mode 100644 index 0000000..154ddbf --- /dev/null +++ b/pyvisa/compat/struct.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.compat.struct + ~~~~~~~~~~~~~~~~~~~~~~~~~ + + Python 2/3 compatibility for struct module + + :copyright: 2015, PSF + :license: PSF License +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import sys +import struct + +# we always want the exception to be able to catch it +error = struct.error + +# compatibility for unicode literals was introduced in 2.7.8 +# if we're above that there is nothing to do except aliasing +if sys.hexversion >= 0x02070800: + pack = struct.pack + pack_into = struct.pack_into + unpack = struct.unpack + unpack_from = struct.unpack_from + calcsize = struct.calcsize +else: + def pack(fmt, *args): + return struct.pack(str(fmt), *args) + + def pack_into(fmt, *args, **argk): + return struct.pack_into(str(fmt), *args, **argk) + + def unpack(fmt, string): + return struct.unpack(str(fmt), string) + + def unpack_from(fmt, *args, **kwargs): + return struct.unpack_from(str(fmt), *args, **kwargs) + + def calcsize(fmt): + return struct.calcsize(str(fmt)) diff --git a/pyvisa/constants.py b/pyvisa/constants.py new file mode 100644 index 0000000..2172306 --- /dev/null +++ b/pyvisa/constants.py @@ -0,0 +1,1060 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.constants + ~~~~~~~~~~~~~~~~ + + 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 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import enum + +from .compat import PYTHON3 + +if PYTHON3: + LongEnum = enum.IntEnum +else: + class LongEnum(long, enum.Enum): + pass + +# _to_int() 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. +# + + +def _to_int(x): + """Converts a completion and error code as it is listed in 32-bit notation + in the VPP-4.3.2 specification to the actual integer value. + """ + if x > 0x7FFFFFFF: + return int(x - 0x100000000) + else: + return int(x) + +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) + +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) + +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 = 0x3FFF0007 +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 + +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 = 0x3FFF0098 +VI_ATTR_WIN_SIZE = 0x3FFF009A +VI_ATTR_ASRL_AVAIL_NUM = 0x3FFF00AC +VI_ATTR_MEM_BASE = 0x3FFF00AD +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 = 0x3FFF00DD +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_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_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 = 0x3FFF4026 +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_USB_RECV_INTR_SIZE = 0x3FFF41B0 +VI_ATTR_USB_RECV_INTR_DATA = 0xBFFF41B1 + + +VI_ATTR_VXI_TRIG_DIR = _to_int(0x3FFF4044) +VI_ATTR_VXI_TRIG_LINES_EN = _to_int(0x3FFF4043) + +# +# 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 + + +# +# 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_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_ECL0 = 8 +VI_TRIG_ECL1 = 9 +VI_TRIG_PANEL_IN = 27 +VI_TRIG_PANEL_OUT = 28 + +VI_TRIG_PROT_DEFAULT = 0 +VI_TRIG_PROT_ON = 1 +VI_TRIG_PROT_OFF = 2 +VI_TRIG_PROT_SYNC = 5 + +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 + +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_WIDTH_8 = 1 +VI_WIDTH_16 = 2 +VI_WIDTH_32 = 4 + +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_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_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 = _to_int(0x3FFF0221) +VI_ATTR_PXI_MEM_BASE_BAR1 = _to_int(0x3FFF0222) +VI_ATTR_PXI_MEM_BASE_BAR2 = _to_int(0x3FFF0223) +VI_ATTR_PXI_MEM_BASE_BAR3 = _to_int(0x3FFF0224) +VI_ATTR_PXI_MEM_BASE_BAR4 = _to_int(0x3FFF0225) +VI_ATTR_PXI_MEM_BASE_BAR5 = _to_int(0x3FFF0226) +VI_ATTR_PXI_MEM_SIZE_BAR0 = _to_int(0x3FFF0231) +VI_ATTR_PXI_MEM_SIZE_BAR1 = _to_int(0x3FFF0232) +VI_ATTR_PXI_MEM_SIZE_BAR2 = _to_int(0x3FFF0233) +VI_ATTR_PXI_MEM_SIZE_BAR3 = _to_int(0x3FFF0234) +VI_ATTR_PXI_MEM_SIZE_BAR4 = _to_int(0x3FFF0235) +VI_ATTR_PXI_MEM_SIZE_BAR5 = _to_int(0x3FFF0236) +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) + +# TODO: What is the value +VI_ATTR_PXI_MEM_BASE_BARX = None +VI_ATTR_PXI_MEM_SIZE_BARX = None +VI_ATTR_PXI_MEM_TYPE_BARX = None + + +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_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 + + +# Enums + +class AccessModes(enum.IntEnum): + + #: Does not obtain any lock on the VISA resource. + no_lock = 0 + + #: Obtains a exclusive lock on the VISA resource. + exclusive_lock = 1 + + #: Obtains a lock on the VISA resouce which may be shared + #: between multiple VISA sessions. + shared_lock = 2 + + +class StopBits(enum.IntEnum): + """The number of stop bits that indicate the end of a frame. + """ + one = VI_ASRL_STOP_ONE + one_and_a_half = VI_ASRL_STOP_ONE5 + two = VI_ASRL_STOP_TWO + + +class Parity(enum.IntEnum): + """The parity types to use with every frame transmitted and received on a serial session. + """ + 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 + + +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 + + +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 + + +class AddressState(enum.IntEnum): + + unaddressed =VI_GPIB_UNADDRESSED + talker = VI_GPIB_TALKER + listenr = VI_GPIB_LISTENER + + +class IOProtocol(enum.IntEnum): + + 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 + + +class LineState(enum.IntEnum): + + asserted = VI_STATE_ASSERTED + unasserted = VI_STATE_UNASSERTED + unknown = VI_STATE_UNKNOWN + + +class EventMechanism(enum.IntEnum): + """The available event mechanisms for event handling. + """ + + queue = VI_QUEUE + handler = VI_HNDLR + + #: events queued but handler not called + suspend_handler = VI_SUSPEND_HNDLR + + all = VI_ALL_MECH + + +# Note that enum.IntEnum fails here for python2: +# OverflowError: Python int too large to convert to C long +# so use LongEnum instead (some values are too large, and ViEventType is unsigned) +class EventType(LongEnum): + """The available event types for event handling. + """ + + io_completion = VI_EVENT_IO_COMPLETION + trig = VI_EVENT_TRIG + service_request = VI_EVENT_SERVICE_REQ + clear = VI_EVENT_CLEAR + exception = VI_EVENT_EXCEPTION + gpib_controller_in_charge = VI_EVENT_GPIB_CIC + gpib_talk = VI_EVENT_GPIB_TALK + gpib_listen = VI_EVENT_GPIB_LISTEN + vxi_vme_sysfail = VI_EVENT_VXI_VME_SYSFAIL + vxi_vme_sysreset = VI_EVENT_VXI_VME_SYSRESET + vxi_signal_interrupt = VI_EVENT_VXI_SIGP + vxi_vme_interrupt = VI_EVENT_VXI_VME_INTR + pxi_interrupt = VI_EVENT_PXI_INTR + tcpip_connect = VI_EVENT_TCPIP_CONNECT + usb_interrupt = VI_EVENT_USB_INTR + all_enabled = VI_ALL_ENABLED_EVENTS + + +class StatusCode(enum.IntEnum): + """Specifies the status codes that NI-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_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_syncronous = 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 diff --git a/pyvisa/ctwrapper/__init__.py b/pyvisa/ctwrapper/__init__.py new file mode 100644 index 0000000..631df6e --- /dev/null +++ b/pyvisa/ctwrapper/__init__.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.ctwrapper + ~~~~~~~~~~~~~~~~ + + ctypes wrapper for NI-VISA library. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +from .highlevel import NIVisaLibrary + +WRAPPER_CLASS = NIVisaLibrary + diff --git a/pyvisa/ctwrapper/cthelper.py b/pyvisa/ctwrapper/cthelper.py new file mode 100644 index 0000000..3599c02 --- /dev/null +++ b/pyvisa/ctwrapper/cthelper.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.ctwrapper._ct + ~~~~~~~~~~~~~~~~~~~~ + + Cross platform helper of ctypes. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +# ctypes and os shouldn't be re-exported. +import os as _os +import sys as _sys + +import ctypes as _ctypes + +PYTHON3 = _sys.version_info >= (3, 0) + +if _os.name == 'nt': + 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. +# noinspection PyUnresolvedReferences +if _os.name == "posix" and _sys.platform.startswith('linux'): + + # Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump + def define_find_libary(): + import re + import tempfile + import errno + + 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): + # XXX assuming GLIBC's ldconfig (with option -p) + expr = r'/[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name) + res = re.search(expr, + _os.popen('/sbin/ldconfig -p 2>/dev/null').read()) + if not res: + # Hm, this works only for libs needed by the python executable. + cmd = 'ldd %s 2>/dev/null' % _sys.executable + res = re.search(expr, _os.popen(cmd).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 diff --git a/pyvisa/ctwrapper/functions.py b/pyvisa/ctwrapper/functions.py new file mode 100644 index 0000000..8208067 --- /dev/null +++ b/pyvisa/ctwrapper/functions.py @@ -0,0 +1,1899 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.ctwrapper.functions + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Defines VPP 4.3.2 wrapping functions using ctypes, adding signatures to the library. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import warnings + +from pyvisa.highlevel import ResourceInfo +from pyvisa import attributes, constants + +from . import types +from .types import * +from ctypes import byref, c_void_p, c_double, c_long, POINTER, create_string_buffer + +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_asynchronously", "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"] + +__all__ = ["visa_functions", 'set_signatures'] + visa_functions + +VI_SPEC_VERSION = 0x00300000 + + +def set_user_handle_type(library, user_handle): + """Set the type of the user handle to install and uninstall handler signature. + + :param library: the visa library wrapped by ctypes. + :param user_handle: use None for a void_p + """ + + # 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)) + + 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] + + +def set_signatures(library, errcheck=None): + """Set the signatures of most visa functions in the library. + + All instrumentation related functions are specified here. + + :param library: the visa library wrapped by ctypes. + :type library: ctypes.WinDLL or ctypes.CDLL + :param errcheck: error checking callable used for visa functions that return + ViStatus. + It should be take three areguments (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_) + # noinspection PyProtectedMember + 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, argtypes, restype, errcheck): + """Set the signature of single function in a library. + + :param library: ctypes wrapped library. + :type library: ctypes.WinDLL or ctypes.CDLL + :param function_name: name of the function as appears in the header file. + :type function_name: str + :param argtypes: a tuple of ctypes types to specify the argument types that the function accepts. + :param restype: A ctypes type to specify the result type of the foreign function. + Use None for void, a function not returning anything. + :param errcheck: a callabe + + :raises: AttributeError + """ + + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param mode: How to assert the interrupt. (Constants.ASSERT*) + :param status_id: This is the status value to be presented during an interrupt acknowledge cycle. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viAssertIntrSignal(session, mode, status_id) + + +def assert_trigger(library, session, protocol): + """Asserts software or hardware trigger. + + Corresponds to viAssertTrigger function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param protocol: Trigger protocol to use during assertion. (Constants.PROT*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viAssertTrigger(session, protocol) + + +def assert_utility_signal(library, session, line): + """Asserts or deasserts the specified utility bus signal. + + Corresponds to viAssertUtilSignal function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param line: specifies the utility bus signal to assert. (Constants.UTIL_ASSERT*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viAssertUtilSignal(session, line) + + +def buffer_read(library, session, count): + """Reads data from device or interface through the use of a formatted I/O read buffer. + + Corresponds to viBufRead function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param count: Number of bytes to be read. + :return: data read, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param data: data to be written. + :type data: bytes + :return: number of written bytes, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viClear(session) + + +def close(library, session): + """Closes the specified session, event, or find list. + + Corresponds to viClose function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session, event, or find list. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viClose(session) + + +def disable_event(library, session, event_type, mechanism): + """Disables notification of the specified event type(s) via the specified mechanism(s). + + Corresponds to viDisableEvent function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param mechanism: Specifies event handling mechanisms to be disabled. + (Constants.VI_QUEUE, .VI_HNDLR, .VI_SUSPEND_HNDLR, .VI_ALL_MECH) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viDisableEvent(session, event_type, mechanism) + + +def discard_events(library, session, event_type, mechanism): + """Discards event occurrences for specified event types and mechanisms in a session. + + Corresponds to viDiscardEvents function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param mechanism: Specifies event handling mechanisms to be dicarded. + (Constants.VI_QUEUE, .VI_HNDLR, .VI_SUSPEND_HNDLR, .VI_ALL_MECH) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param mechanism: Specifies event handling mechanisms to be enabled. + (Constants.VI_QUEUE, .VI_HNDLR, .VI_SUSPEND_HNDLR) + :param context: + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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): + """Returns the next resource from the list of resources found during a previous call to find_resources(). + + Corresponds to viFindNext function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param find_list: Describes a find list. This parameter must be created by find_resources(). + :return: Returns a string identifying the location of a device, return value of the library call. + :rtype: unicode (Py2) or str (Py3), :class:`pyvisa.constants.StatusCode` + """ + 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, query): + """Queries a VISA system to locate the resources associated with a specified interface. + + Corresponds to viFindRsrc function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session (unused, just to uniform signatures). + :param query: A regular expression followed by an optional logical expression. Use '?*' for all. + :return: find_list, return_counter, instrument_description, return value of the library call. + :rtype: ViFindList, int, unicode (Py2) or str (Py3), :class:`pyvisa.constants.StatusCode` + """ + find_list = ViFindList() + return_counter = ViUInt32() + instrument_description = create_string_buffer(constants.VI_FIND_BUFLEN) + + # [ViSession, ViString, ViPFindList, ViPUInt32, ViAChar] + # ViString converts from (str, unicode, bytes) to bytes + 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): + """Manually flushes the specified buffers associated with formatted I/O operations and/or serial communication. + + Corresponds to viFlush function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param mask: Specifies the action to be taken with flushing the buffer. + (Constants.READ*, .WRITE*, .IO*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session, event, or find list. + :param attribute: Resource attribute for which the state query is made (see Attributes.*) + :return: The state of the queried attribute for a specified resource, return value of the library call. + :rtype: unicode (Py2) or str (Py3), list or other type, :class:`pyvisa.constants.StatusCode` + """ + + # FixMe: How to deal with ViBuf? + 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 + elif datatype == ViAUInt8: + 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: + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param data: data tor write. + :type data: bytes + :return: Number of written bytes, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param mode: Specifies the state of the ATN line and optionally the local active controller state. + (Constants.GPIB_ATN*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viGpibControlATN(session, mode) + + +def gpib_control_ren(library, session, mode): + """Controls the state of the GPIB Remote Enable (REN) interface line, and optionally the remote/local + state of the device. + + Corresponds to viGpibControlREN function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param mode: Specifies the state of the REN line and optionally the device remote/local state. + (Constants.GPIB_REN*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viGpibControlREN(session, mode) + + +def gpib_pass_control(library, session, primary_address, secondary_address): + """Tell the GPIB device at the specified address to become controller in charge (CIC). + + Corresponds to viGpibPassControl function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param primary_address: Primary address of the GPIB device to which you want to pass control. + :param secondary_address: 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. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viGpibSendIFC(session) + + +def read_memory(library, session, space, offset, width, extended=False): + """Reads in an 8-bit, 16-bit, 32-bit, or 64-bit value from the specified memory space and offset. + + Corresponds to viIn* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param width: Number of bits to read. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from memory, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + if width == 8: + return in_8(library, session, space, offset, extended) + elif width == 16: + return in_16(library, session, space, offset, extended) + elif width == 32: + return in_32(library, session, space, offset, extended) + elif width == 64: + return in_64(library, session, space, offset, extended) + + raise ValueError('%s is not a valid size. Valid values are 8, 16, 32 or 64' % width) + + +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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from memory, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from memory, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from memory, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from memory, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + 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): + """Installs handlers for event callbacks. + + Corresponds to viInstallHandler function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param handler: Interpreted as a valid reference to a handler to be installed by a client application. + :param user_handle: A value specified by an application that can be used for identifying handlers + uniquely for an event type. Can be a regular python object (int, float, str, list + of floats or ints) or a ctypes object. + :returns: a handler descriptor which consists of three elements: + - handler (a python callable) + - user handle (a ctypes object) + - ctypes handler (ctypes object wrapping handler) + and return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + if user_handle is None: + converted_user_handle = None + else: + 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 = create_string_buffer(user_handle) + elif isinstance(user_handle, list): + for element in user_handle: + if not isinstance(element, int): + converted_user_handle = \ + (c_double * len(user_handle))(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)) + + set_user_handle_type(library, converted_user_handle) + converted_handler = ViHndlr(handler) + 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)) + + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param lock_type: Specifies the type of lock requested, either constants.AccessModes.exclusive_lock + or constants.AccessModes.shared_lock. + :param timeout: Absolute time period (in milliseconds) that a resource waits to get unlocked by the + locking session before returning an error. + :param requested_key: This parameter is not used and should be set to VI_NULL when lockType is VI_EXCLUSIVE_LOCK. + :return: access_key that can then be passed to other sessions to share the lock, return value of the library call. + :rtype: str, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param map_space: Specifies the address space to map. (Constants.*SPACE*) + :param map_base: Offset (in bytes) of the memory to be mapped. + :param map_size: Amount of memory to map (in bytes). + :param access: + :param suggested: If not Constants.NULL (0), the operating system attempts to map the memory to the address + specified in suggested. 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 + suggested. + + :return: address in your process space where the memory was mapped, return value of the library call. + :rtype: address, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param trigger_source: Source line from which to map. (Constants.TRIG*) + :param trigger_destination: Destination line to which to map. (Constants.TRIG*) + :param mode: + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viMapTrigger(session, trigger_source, trigger_destination, mode) + + +def memory_allocation(library, session, size, extended=False): + """Allocates memory from a resource's memory region. + + Corresponds to viMemAlloc* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param size: Specifies the size of the allocation. + :param extended: Use 64 bits offset independent of the platform. + :return: offset of the allocated memory, return value of the library call. + :rtype: offset, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param offset: Offset of the memory to free. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param source_space: Specifies the address space of the source. + :param source_offset: Offset of the starting address or register from which to read. + :param source_width: Specifies the data width of the source. + :param destination_space: Specifies the address space of the destination. + :param destination_offset: Offset of the starting address or register to which to write. + :param destination_width: Specifies the data width of the destination. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param source_space: Specifies the address space of the source. + :param source_offset: Offset of the starting address or register from which to read. + :param source_width: Specifies the data width of the source. + :param destination_space: Specifies the address space of the destination. + :param destination_offset: Offset of the starting address or register to which to write. + :param destination_width: Specifies the data width of the destination. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :return: Job identifier of this asynchronous move operation, return value of the library call. + :rtype: jobid, :class:`pyvisa.constants.StatusCode` + """ + 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(library, session, space, offset, length, width, extended=False): + """Moves a block of data to local memory from the specified address space and offset. + + Corresponds to viMoveIn* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param width: Number of bits to read per element. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from the bus, return value of the library call. + :rtype: list, :class:`pyvisa.constants.StatusCode` + """ + if width == 8: + return move_in_8(library, session, space, offset, length, extended) + elif width == 16: + return move_in_16(library, session, space, offset, length, extended) + elif width == 32: + return move_in_32(library, session, space, offset, length, extended) + elif width == 64: + return move_in_64(library, session, space, offset, length, extended) + + raise ValueError('%s is not a valid size. Valid values are 8, 16, 32 or 64' % width) + + +def move_in_8(library, session, space, offset, length, extended=False): + """Moves an 8-bit block of data from the specified address space and offset to local memory. + + Corresponds to viMoveIn8* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from the bus, return value of the library call. + :rtype: list, :class:`pyvisa.constants.StatusCode` + """ + 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 from the specified address space and offset to local memory. + + Corresponds to viMoveIn16* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from the bus, return value of the library call. + :rtype: list, :class:`pyvisa.constants.StatusCode` + """ + 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 from the specified address space and offset to local memory. + + Corresponds to viMoveIn32* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from the bus, return value of the library call. + :rtype: list, :class:`pyvisa.constants.StatusCode` + """ + 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 from the specified address space and offset to local memory. + + Corresponds to viMoveIn64* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from the bus, return value of the library call. + :rtype: list, :class:`pyvisa.constants.StatusCode` + """ + 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(library, session, space, offset, length, data, width, extended=False): + """Moves a block of data from local memory to the specified address space and offset. + + Corresponds to viMoveOut* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param data: Data to write to bus. + :param width: Number of bits to read per element. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + if width == 8: + return move_out_8(library, session, space, offset, length, data, extended) + elif width == 16: + return move_out_16(library, session, space, offset, length, data, extended) + elif width == 32: + return move_out_32(library, session, space, offset, length, data, extended) + elif width == 64: + return move_out_64(library, session, space, offset, length, data, extended) + + raise ValueError('%s is not a valid size. Valid values are 8, 16, 32 or 64' % width) + + +def move_out_8(library, session, space, offset, length, data, extended=False): + """Moves an 8-bit block of data from local memory to the specified address space and offset. + + Corresponds to viMoveOut8* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + + Corresponds to viMoveOut8 function of the VISA library. + """ + 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 to the specified address space and offset. + + Corresponds to viMoveOut16* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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 to the specified address space and offset. + + Corresponds to viMoveOut32* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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 to the specified address space and offset. + + Corresponds to viMoveOut64* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Resource Manager session (should always be a session returned from open_default_resource_manager()). + :param resource_name: Unique symbolic name of a resource. + :param access_mode: Specifies the mode by which the resource is to be accessed. (constants.AccessModes) + :param open_timeout: Specifies the maximum time period (in milliseconds) that this operation waits + before returning an error. + :return: Unique logical identifier reference to a session, return value of the library call. + :rtype: session, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :return: Unique logical identifier to a Default Resource Manager session, return value of the library call. + :rtype: session, :class:`pyvisa.constants.StatusCode` + """ + session = ViSession() + ret = library.viOpenDefaultRM(byref(session)) + return session.value, ret + + +def write_memory(library, session, space, offset, data, width, extended=False): + """Write in an 8-bit, 16-bit, 32-bit, value to the specified memory space and offset. + + Corresponds to viOut* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param data: Data to write to bus. + :param width: Number of bits to read. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + if width == 8: + return out_8(library, session, space, offset, data, extended) + elif width == 16: + return out_16(library, session, space, offset, data, extended) + elif width == 32: + return out_32(library, session, space, offset, data, extended) + + raise ValueError('%s is not a valid size. Valid values are 8, 16 or 32' % width) + + +def out_8(library, session, space, offset, data, extended=False): + """Write in an 8-bit value from the specified memory space and offset. + + Corresponds to viOut8* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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 in an 16-bit value from the specified memory space and offset. + + Corresponds to viOut16* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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 in an 32-bit value from the specified memory space and offset. + + Corresponds to viOut32* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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 in an 64-bit value from the specified memory space and offset. + + Corresponds to viOut64* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Resource Manager session (should always be the Default Resource Manager for VISA + returned from open_default_resource_manager()). + :param resource_name: Unique symbolic name of a resource. + :return: Resource information with interface type and board number, return value of the library call. + :rtype: :class:`pyvisa.highlevel.ResourceInfo`, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Resource Manager session (should always be the Default Resource Manager for VISA + returned from open_default_resource_manager()). + :param resource_name: Unique symbolic name of a resource. + :return: Resource information, return value of the library call. + :rtype: :class:`pyvisa.highlevel.ResourceInfo`, :class:`pyvisa.constants.StatusCode` + """ + 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(library, session, address, width): + """Read an 8, 16 or 32-bit value from the specified address. + + Corresponds to viPeek* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param width: Number of bits to read. + :return: Data read from bus, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + + if width == 8: + return peek_8(library, session, address) + elif width == 16: + return peek_16(library, session, address) + elif width == 32: + return peek_32(library, session, address) + elif width == 64: + return peek_64(library, session, address) + + raise ValueError('%s is not a valid size. Valid values are 8, 16, 32 or 64' % width) + + +def peek_8(library, session, address): + """Read an 8-bit value from the specified address. + + Corresponds to viPeek8 function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :return: Data read from bus, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :return: Data read from bus, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :return: Data read from bus, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :return: Data read from bus, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + value_64 = ViUInt64() + ret = library.viPeek64(session, address, byref(value_64)) + return value_64.value, ret + + +def poke(library, session, address, width, data): + """Writes an 8, 16 or 32-bit value from the specified address. + + Corresponds to viPoke* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param width: Number of bits to read. + :param data: Data to be written to the bus. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + + if width == 8: + return poke_8(library, session, address, data) + elif width == 16: + return poke_16(library, session, address, data) + elif width == 32: + return poke_32(library, session, address, data) + + raise ValueError('%s is not a valid size. Valid values are 8, 16 or 32' % width) + + +def poke_8(library, session, address, data): + """Write an 8-bit value from the specified address. + + Corresponds to viPoke8 function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param data: value to be written to the bus. + :return: Data read from bus. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viPoke8(session, address, data) + + +def poke_16(library, session, address, data): + """Write an 16-bit value from the specified address. + + Corresponds to viPoke16 function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param data: value to be written to the bus. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viPoke16(session, address, data) + + +def poke_32(library, session, address, data): + """Write an 32-bit value from the specified address. + + Corresponds to viPoke32 function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param data: value to be written to the bus. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viPoke32(session, address, data) + + +def poke_64(library, session, address, data): + """Write an 64-bit value from the specified address. + + Corresponds to viPoke64 function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param data: value to be written to the bus. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param count: Number of bytes to be read. + :return: data read, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + 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_asynchronously(library, session, count): + """Reads data from device or interface asynchronously. + + Corresponds to viReadAsync function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param count: Number of bytes to be read. + :return: result, jobid, return value of the library call. + :rtype: ctypes buffer, jobid, :class:`pyvisa.constants.StatusCode` + """ + buffer = create_string_buffer(count) + job_id = ViJobId() + ret = library.viReadAsync(session, buffer, count, byref(job_id)) + return buffer, job_id, ret + + +def read_stb(library, session): + """Reads a status byte of the service request. + + Corresponds to viReadSTB function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :return: Service request status byte, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param filename: Name of file to which data will be written. + :param count: Number of bytes to be read. + :return: Number of bytes actually transferred, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + return_count = ViUInt32() + ret = library.viReadToFile(session, filename, count, return_count) + return return_count, ret + + +def set_attribute(library, session, attribute, attribute_state): + """Sets the state of an attribute. + + Corresponds to viSetAttribute function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param attribute: Attribute for which the state is to be modified. (Attributes.*) + :param attribute_state: The state of the attribute to be set for the specified object. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viSetAttribute(session, attribute, attribute_state) + + +def set_buffer(library, session, mask, size): + """Sets the size for the formatted I/O and/or low-level I/O communication buffer(s). + + Corresponds to viSetBuf function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param mask: Specifies the type of buffer. (Constants.READ_BUF, .WRITE_BUF, .IO_IN_BUF, .IO_OUT_BUF) + :param size: The size to be set for the specified buffer(s). + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viSetBuf(session, mask, size) + + +def status_description(library, session, status): + """Returns a user-readable description of the status code passed to the operation. + + Corresponds to viStatusDesc function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param status: Status code to interpret. + :return: - The user-readable string interpretation of the status code passed to the operation, + - return value of the library call. + :rtype: - unicode (Py2) or str (Py3) + - :class:`pyvisa.constants.StatusCode` + """ + description = create_string_buffer(256) + ret = library.viStatusDesc(session, status, description) + return buffer_to_text(description), ret + + +def terminate(library, session, degree, job_id): + """Requests a VISA session to terminate normal execution of an operation. + + Corresponds to viTerminate function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param degree: Constants.NULL + :param job_id: Specifies an operation identifier. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viTerminate(session, degree, job_id) + + +def uninstall_handler(library, session, event_type, handler, user_handle=None): + """Uninstalls handlers for events. + + Corresponds to viUninstallHandler function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param handler: Interpreted as a valid reference to a handler to be uninstalled by a client application. + :param user_handle: The user_handle (a ctypes object) in the returned value from install_handler. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + set_user_handle_type(library, user_handle) + if user_handle != None: + user_handle = byref(user_handle) + return library.viUninstallHandler(session, event_type, handler, user_handle) + + +def unlock(library, session): + """Relinquishes a lock for the specified resource. + + Corresponds to viUnlock function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viUnlock(session) + + +def unmap_address(library, session): + """Unmaps memory space previously mapped by map_address(). + + Corresponds to viUnmapAddress function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viUnmapAddress(session) + + +def unmap_trigger(library, session, trigger_source, trigger_destination): + """Undo a previous map from the specified trigger source line to the specified destination line. + + Corresponds to viUnmapTrigger function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param trigger_source: Source line used in previous map. (Constants.TRIG*) + :param trigger_destination: Destination line used in previous map. (Constants.TRIG*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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): + """Performs a USB control pipe transfer from the device. + + Corresponds to viUsbControlIn function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param request_type_bitmap_field: bmRequestType parameter of the setup stage of a USB control transfer. + :param request_id: bRequest parameter of the setup stage of a USB control transfer. + :param request_value: wValue parameter of the setup stage of a USB control transfer. + :param index: wIndex parameter of the setup stage of a USB control transfer. + This is usually the index of the interface or endpoint. + :param length: 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. + :return: - The data buffer that receives the data from the optional data stage of the control transfer + - return value of the library call. + :rtype: - bytes + - :class:`pyvisa.constants.StatusCode` + """ + 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=""): + """Performs a USB control pipe transfer to the device. + + Corresponds to viUsbControlOut function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param request_type_bitmap_field: bmRequestType parameter of the setup stage of a USB control transfer. + :param request_id: bRequest parameter of the setup stage of a USB control transfer. + :param request_value: wValue parameter of the setup stage of a USB control transfer. + :param index: wIndex parameter of the setup stage of a USB control transfer. + This is usually the index of the interface or endpoint. + :param data: The data buffer that sends the data in the optional data stage of the control transfer. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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): + """Sends the device a miscellaneous command or query and/or retrieves the response to a previous query. + + Corresponds to viVxiCommandQuery function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param mode: Specifies whether to issue a command and/or retrieve a response. (Constants.VXI_CMD*, .VXI_RESP*) + :param command: The miscellaneous command to send. + :return: The response retrieved from the device, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + response = ViUInt32() + ret = library.viVxiCommandQuery(session, mode, command, byref(response)) + return response.value, ret + + +def wait_on_event(library, session, in_event_type, timeout): + """Waits for an occurrence of the specified event for a given session. + + Corresponds to viWaitOnEvent function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param in_event_type: Logical identifier of the event(s) to wait for. + :param timeout: 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. + :return: - Logical identifier of the event actually received + - A handle specifying the unique occurrence of an event + - return value of the library call. + :rtype: - eventtype + - event + - :class:`pyvisa.constants.StatusCode` + """ + 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): + """Writes data to device or interface synchronously. + + Corresponds to viWrite function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param data: data to be written. + :type data: str + :return: Number of bytes actually transferred, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + 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): + """Writes data to device or interface asynchronously. + + Corresponds to viWriteAsync function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param data: data to be written. + :return: Job ID of this asynchronous write operation, return value of the library call. + :rtype: jobid, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param filename: Name of file from which data will be read. + :param count: Number of bytes to be written. + :return: Number of bytes actually transferred, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + return_count = ViUInt32() + ret = library.viWriteFromFile(session, filename, count, return_count) + return return_count, ret diff --git a/pyvisa/ctwrapper/highlevel.py b/pyvisa/ctwrapper/highlevel.py new file mode 100644 index 0000000..1399046 --- /dev/null +++ b/pyvisa/ctwrapper/highlevel.py @@ -0,0 +1,218 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.ctwrapper.highlevel + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Highlevel wrapper of the VISA Library. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import logging +import warnings + +from pyvisa import constants, errors, highlevel, logger +from pyvisa.compat import integer_types, OrderedDict + +from .cthelper import Library, find_library +from . import functions + + +logger = logging.LoggerAdapter(logger, {'backend': 'ni'}) + + +def add_visa_methods(aclass): + for method in functions.visa_functions: + setattr(aclass, method, getattr(functions, method)) + return aclass + + +def _args_to_str(args): + out = [] + for arg in args: + try: + # noinspection PyProtectedMember + out.append(str(arg._obj)) + except AttributeError: + out.append(arg) + return tuple(out) + + +@add_visa_methods +class NIVisaLibrary(highlevel.VisaLibraryBase): + """High level NI-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 = NIVisaLibrary() + + But you can also specify the path: + + >>> visa_library = NIVisaLibrary('/my/path/visa.so') + + :param library_path: path of the VISA library. + """ + + @staticmethod + def get_library_paths(): + """Return a tuple of possible library paths. + + :rtype: tuple + """ + + from ..util import LibraryPath, read_user_library_path + + user_lib = read_user_library_path() + tmp = [find_library(library_path) + for library_path in ('visa', 'visa32', 'visa32.dll')] + + tmp = [LibraryPath(library_path) + for library_path in tmp + if library_path is not None] + + logger.debug('Automatically found library files: %s' % tmp) + + if user_lib: + user_lib = LibraryPath(user_lib, 'user') + try: + tmp.remove(user_lib) + except ValueError: + pass + tmp.insert(0, user_lib) + + return tuple(tmp) + + @staticmethod + def get_debug_info(): + """Return a list of lines with backend info. + """ + from pyvisa import __version__ + d = OrderedDict() + d['Version'] = '%s (bundled with PyVISA)' % __version__ + + paths = NIVisaLibrary.get_library_paths() + + for ndx, visalib in enumerate(paths, 1): + nfo = OrderedDict() + nfo['found by'] = visalib.found_by + nfo['bitness'] = visalib.bitness + try: + lib = NIVisaLibrary(visalib) + sess, _ = lib.open_default_resource_manager() + nfo['Vendor'] = str(lib.get_attribute(sess, constants.VI_ATTR_RSRC_MANF_NAME)[0]) + nfo['Impl. Version'] = str(lib.get_attribute(sess, constants.VI_ATTR_RSRC_IMPL_VERSION)[0]) + nfo['Spec. Version'] = str(lib.get_attribute(sess, constants.VI_ATTR_RSRC_SPEC_VERSION)[0]) + lib.close(sess) + except Exception as e: + e = str(e) + if 'No matching architecture' in e: + nfo['Could not get more info'] = 'Interpreter and library have different bitness.' + else: + nfo['Could not get more info'] = str(e).split('\n') + + d['#%d: %s' % (ndx, visalib)] = nfo + + if not paths: + d['Binary library'] = 'Not found' + + return d + + def _init(self): + try: + lib = Library(self.library_path) + except OSError as exc: + raise errors.LibraryError.from_exception(exc, self.library_path) + + self.lib = lib + + # 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, func, arguments): + """Check return values for errors and warnings. + """ + + logger.debug('%s%s -> %r', + func.__name__, _args_to_str(arguments), ret_value, + extra=self._logging_extra) + + try: + ret_value = constants.StatusCode(ret_value) + except ValueError: + pass + + self._last_status = ret_value + + # 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', ): + # noinspection PyProtectedMember + session = session._obj.value + + if isinstance(session, integer_types): + self._last_status_in_session[session] = ret_value + else: + # Functions that might or might 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))) + + if ret_value < 0: + raise errors.VisaIOError(ret_value) + + if ret_value in self.issue_warning_on: + if session and ret_value not in self._ignore_warning_in_session[session]: + warnings.warn(errors.VisaIOWarning(ret_value), stacklevel=2) + + return ret_value + + def list_resources(self, session, query='?*::INSTR'): + """Returns a tuple of all connected devices matching query. + + :param query: regular expression used to match devices. + """ + + resources = [] + + try: + find_list, return_counter, instrument_description, err = self.find_resources(session, query) + except errors.VisaIOError as e: + if e.error_code == constants.StatusCode.error_resource_not_found: + return tuple() + raise e + + resources.append(instrument_description) + for i in range(return_counter - 1): + resources.append(self.find_next(find_list)[0]) + + self.close(find_list) + + return tuple(resource for resource in resources) + diff --git a/pyvisa/ctwrapper/types.py b/pyvisa/ctwrapper/types.py new file mode 100644 index 0000000..96cde28 --- /dev/null +++ b/pyvisa/ctwrapper/types.py @@ -0,0 +1,157 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.ctwrapper.types + ~~~~~~~~~~~~~~~~~~~~~~ + + 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 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import ctypes as _ctypes + +from .cthelper import PYTHON3, 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) + + +if PYTHON3: + 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 + +else: + + class ViString(object): + + @classmethod + def from_param(cls, obj): + if isinstance(obj, str): + return obj + elif isinstance(obj, unicode): + return obj.encode('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): + 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): + + @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) diff --git a/pyvisa/errors.py b/pyvisa/errors.py new file mode 100644 index 0000000..94ec7d1 --- /dev/null +++ b/pyvisa/errors.py @@ -0,0 +1,513 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.errors + ~~~~~~~~~~~~~ + + Defines exceptions hierarchy and textual explanations of VISA completion and error codes. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, print_function, absolute_import + +from . import util, constants +from .constants import * + +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([VI_SUCCESS_MAX_CNT, VI_SUCCESS_DEV_NPRESENT, + VI_SUCCESS_SYNC, VI_WARN_QUEUE_OVERFLOW, + VI_WARN_CONFIG_NLOADED, VI_WARN_NULL_OBJECT, + VI_WARN_NSUP_ATTR_STATE, VI_WARN_UNKNOWN_STATUS, + VI_WARN_NSUP_BUF, VI_WARN_EXT_FUNC_NIMPL]) + + +class Error(Exception): + """Abstract basic exception class for this module.""" + + def __init__(self, description): + super(Error, self).__init__(description) + + +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): + 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 + + +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): + 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 + + +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, handler, user_handle): + super(UnknownHandler, self).__init__('%s, %s, %s' % (event_type, handler, user_handle)) + + +class OSNotSupported(Error): + + def __init__(self, os): + super(OSNotSupported, self).__init__(os + " is not yet supported by PyVISA") + + +class InvalidBinaryFormat(Error): + + def __init__(self, description=""): + if description: + description = ": " + description + super(InvalidBinaryFormat, self).__init__("Unrecognized binary data format" + description) + + +class InvalidSession(Error): + """Exception raised when an invalid session is requested. + """ + + def __init__(self): + super(InvalidSession, self).__init__('Invalid session handle. The resource might be closed.') + + +class LibraryError(OSError, Error): + + @classmethod + def from_exception(cls, exc, filename): + + 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): + 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)) + + +def _args_to_str(args, kwargs): + return 'args=%s, kwargs=%s' % (args, kwargs) + + +def return_handler(module_logger, first_is_session=True): + """Decorator for VISA library classes. + """ + + 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 = constants.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 diff --git a/pyvisa/highlevel.py b/pyvisa/highlevel.py new file mode 100644 index 0000000..a07f34a --- /dev/null +++ b/pyvisa/highlevel.py @@ -0,0 +1,1652 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.highlevel + ~~~~~~~~~~~~~~~~ + + High level Visa library wrapper. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import contextlib +import collections +import pkgutil +from collections import defaultdict + +from . import logger +from . import constants +from . import errors +from . import rname + +#: 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. +#: :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 = collections.namedtuple('ResourceInfo', + 'interface_type interface_board_number ' + 'resource_class resource_name alias') + + +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. + + The default VisaLibrary class is :class:`pyvisa.ctwrapper.highlevel.NIVisaLibrary`, + which implements a ctypes wrapper around the NI-VISA library. + + 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 visa + >>> rm = visa.ResourceManager("/path/to/my/libvisa.so.7") + >>> lib = rm.visalib + """ + + #: Default ResourceManager instance for this library. + resource_manager = None + + #: Maps library path to VisaLibrary object + _registry = dict() + + #: Last return value of the library. + _last_status = 0 + + #: Maps session handle to last status. dict() + _last_status_in_session = None + + #: Maps session handle to warnings to ignore. defaultdict(set) + _ignore_warning_in_session = None + + #: Contains all installed event handlers. + #: Its elements are tuples with three elements: The handler itself (a Python + #: callable), the user handle (as a ct object) and the handler again, this + #: time as a ct object created with CFUNCTYPE. + handlers = None + + #: Set error codes on which to issue a warning. set + issue_warning_on = None + + def __new__(cls, library_path=''): + 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 (cls, library_path) in cls._registry: + return cls._registry[(cls, library_path)] + + obj = super(VisaLibraryBase, cls).__new__(cls) + + obj.library_path = library_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) + + logger.debug('Created library wrapper for %s', library_path) + + cls._registry[(cls, library_path)] = obj + + return obj + + @staticmethod + def get_library_paths(): + """Override this method to return an iterable of possible library_paths + to try in case that no argument is given. + """ + return 'unset', + + @staticmethod + def get_debug_info(): + """Override this method to return an iterable of lines with the backend debug details. + """ + return ['Does not provide debug info'] + + def _init(self): + """Override this method to customize VisaLibrary initialization. + """ + pass + + def __str__(self): + return 'Visa Library at %s' % self.library_path + + def __repr__(self): + return '' % self.library_path + + @property + def last_status(self): + """Last return value of the library. + """ + return self._last_status + + def get_last_status_in_session(self, session): + """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, *warnings_constants): + """A session dependent context for ignoring warnings + + :param session: Unique logical identifier to a session. + :param warnings_constants: 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, event_type, handler, user_handle=None): + """Installs handlers for event callbacks. + + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param handler: Interpreted as a valid reference to a handler to be installed by a client application. + :param user_handle: A value specified by an application that can be used for identifying handlers + uniquely for an event type. + :returns: user handle (a ctypes object) + """ + try: + new_handler = self.install_handler(session, event_type, handler, user_handle) + except TypeError as e: + raise errors.VisaTypeError(str(e)) + + self.handlers[session].append(new_handler + (event_type,)) + return new_handler[1] + + def uninstall_visa_handler(self, session, event_type, handler, user_handle=None): + """Uninstalls handlers for events. + + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param handler: Interpreted as a valid reference to a handler to be uninstalled by a client application. + :param user_handle: The user handle (ctypes object or None) returned by install_visa_handler. + """ + for ndx, element in enumerate(self.handlers[session]): + if element[0] is handler and element[1] is user_handle and element[4] == 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): + for element in self.handlers[session]: + self.uninstall_handler(session, element[4], element[2], element[1]) + del self.handlers[session] + + def uninstall_all_visa_handlers(self, session): + """Uninstalls all previously installed handlers for a particular session. + + :param session: 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, space, offset, width, extended=False): + """Reads in an 8-bit, 16-bit, 32-bit, or 64-bit value from the specified memory space and offset. + + Corresponds to viIn* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param width: Number of bits to read. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from memory, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + if width == 8: + return self.in_8(session, space, offset, extended) + elif width == 16: + return self.in_16(session, space, offset, extended) + elif width == 32: + return self.in_32(session, space, offset, extended) + elif width == 64: + return self.in_64(session, space, offset, extended) + + raise ValueError('%s is not a valid size. Valid values are 8, 16, 32 or 64' % width) + + def write_memory(self, session, space, offset, data, width, extended=False): + """Write in an 8-bit, 16-bit, 32-bit, value to the specified memory space and offset. + + Corresponds to viOut* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param data: Data to write to bus. + :param width: Number of bits to read. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + if width == 8: + return self.out_8(session, space, offset, data, extended) + elif width == 16: + return self.out_16(session, space, offset, data, extended) + elif width == 32: + return self.out_32(session, space, offset, data, extended) + + raise ValueError('%s is not a valid size. Valid values are 8, 16 or 32' % width) + + def move_in(self, session, space, offset, length, width, extended=False): + """Moves a block of data to local memory from the specified address space and offset. + + Corresponds to viMoveIn* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param width: Number of bits to read per element. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from the bus, return value of the library call. + :rtype: list, :class:`pyvisa.constants.StatusCode` + """ + if width == 8: + return self.move_in_8(session, space, offset, length, extended) + elif width == 16: + return self.move_in_16(session, space, offset, length, extended) + elif width == 32: + return self.move_in_32(session, space, offset, length, extended) + elif width == 64: + return self.move_in_64(session, space, offset, length, extended) + + raise ValueError('%s is not a valid size. Valid values are 8, 16, 32 or 64' % width) + + def move_out(self, session, space, offset, length, data, width, extended=False): + """Moves a block of data from local memory to the specified address space and offset. + + Corresponds to viMoveOut* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param data: Data to write to bus. + :param width: Number of bits to read per element. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + if width == 8: + return self.move_out_8(session, space, offset, length, data, extended) + elif width == 16: + return self.move_out_16(session, space, offset, length, data, extended) + elif width == 32: + return self.move_out_32(session, space, offset, length, data, extended) + elif width == 64: + return self.move_out_64(session, space, offset, length, data, extended) + + raise ValueError('%s is not a valid size. Valid values are 8, 16, 32 or 64' % width) + + def peek(self, session, address, width): + """Read an 8, 16 or 32-bit value from the specified address. + + Corresponds to viPeek* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param width: Number of bits to read. + :return: Data read from bus, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + + if width == 8: + return self.peek_8(session, address) + elif width == 16: + return self.peek_16(session, address) + elif width == 32: + return self.peek_32(session, address) + elif width == 64: + return self.peek_64(session, address) + + raise ValueError('%s is not a valid size. Valid values are 8, 16, 32 or 64' % width) + + def poke(self, session, address, width, data): + """Writes an 8, 16 or 32-bit value from the specified address. + + Corresponds to viPoke* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param width: Number of bits to read. + :param data: Data to be written to the bus. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + + if width == 8: + return self.poke_8(session, address, data) + elif width == 16: + return self.poke_16(session, address, data) + elif width == 32: + return self.poke_32(session, address, data) + + raise ValueError('%s is not a valid size. Valid values are 8, 16 or 32' % width) + + # Methods that VISA Library implementations must implement + + def assert_interrupt_signal(self, session, mode, status_id): + """Asserts the specified interrupt or signal. + + Corresponds to viAssertIntrSignal function of the VISA library. + + :param session: Unique logical identifier to a session. + :param mode: How to assert the interrupt. (Constants.ASSERT*) + :param status_id: This is the status value to be presented during an interrupt acknowledge cycle. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def assert_trigger(self, session, protocol): + """Asserts software or hardware trigger. + + Corresponds to viAssertTrigger function of the VISA library. + + :param session: Unique logical identifier to a session. + :param protocol: Trigger protocol to use during assertion. (Constants.PROT*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def assert_utility_signal(self, session, line): + """Asserts or deasserts the specified utility bus signal. + + Corresponds to viAssertUtilSignal function of the VISA library. + + :param session: Unique logical identifier to a session. + :param line: specifies the utility bus signal to assert. (Constants.VI_UTIL_ASSERT*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def buffer_read(self, session, count): + """Reads data from device or interface through the use of a formatted I/O read buffer. + + Corresponds to viBufRead function of the VISA library. + + :param session: Unique logical identifier to a session. + :param count: Number of bytes to be read. + :return: data read, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def buffer_write(self, session, data): + """Writes data to a formatted I/O write buffer synchronously. + + Corresponds to viBufWrite function of the VISA library. + + :param session: Unique logical identifier to a session. + :param data: data to be written. + :type data: bytes + :return: number of written bytes, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def clear(self, session): + """Clears a device. + + Corresponds to viClear function of the VISA library. + + :param session: Unique logical identifier to a session. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def close(self, session): + """Closes the specified session, event, or find list. + + Corresponds to viClose function of the VISA library. + + :param session: Unique logical identifier to a session, event, or find list. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def disable_event(self, session, event_type, mechanism): + """Disables notification of the specified event type(s) via the specified mechanism(s). + + Corresponds to viDisableEvent function of the VISA library. + + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param mechanism: Specifies event handling mechanisms to be disabled. + (Constants.VI_QUEUE, .VI_HNDLR, .VI_SUSPEND_HNDLR, .VI_ALL_MECH) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def discard_events(self, session, event_type, mechanism): + """Discards event occurrences for specified event types and mechanisms in a session. + + Corresponds to viDiscardEvents function of the VISA library. + + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param mechanism: Specifies event handling mechanisms to be discarded. + (Constants.VI_QUEUE, .VI_HNDLR, .VI_SUSPEND_HNDLR, .VI_ALL_MECH) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def enable_event(self, 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. + + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param mechanism: Specifies event handling mechanisms to be enabled. + (Constants.VI_QUEUE, .VI_HNDLR, .VI_SUSPEND_HNDLR) + :param context: + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def flush(self, session, mask): + """Manually flushes the specified buffers associated with formatted I/O operations and/or serial communication. + + Corresponds to viFlush function of the VISA library. + + :param session: Unique logical identifier to a session. + :param mask: Specifies the action to be taken with flushing the buffer. + (Constants.READ*, .WRITE*, .IO*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def get_attribute(self, session, attribute): + """Retrieves the state of an attribute. + + Corresponds to viGetAttribute function of the VISA library. + + :param session: Unique logical identifier to a session, event, or find list. + :param attribute: Resource attribute for which the state query is made (see Attributes.*) + :return: The state of the queried attribute for a specified resource, return value of the library call. + :rtype: unicode (Py2) or str (Py3), list or other type, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def gpib_command(self, session, data): + """Write GPIB command bytes on the bus. + + Corresponds to viGpibCommand function of the VISA library. + + :param session: Unique logical identifier to a session. + :param data: data tor write. + :type data: bytes + :return: Number of written bytes, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def gpib_control_atn(self, session, mode): + """Specifies the state of the ATN line and the local active controller state. + + Corresponds to viGpibControlATN function of the VISA library. + + :param session: Unique logical identifier to a session. + :param mode: Specifies the state of the ATN line and optionally the local active controller state. + (Constants.VI_GPIB_ATN*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def gpib_control_ren(self, session, mode): + """Controls the state of the GPIB Remote Enable (REN) interface line, and optionally the remote/local + state of the device. + + Corresponds to viGpibControlREN function of the VISA library. + + :param session: Unique logical identifier to a session. + :param mode: Specifies the state of the REN line and optionally the device remote/local state. + (Constants.VI_GPIB_REN*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def gpib_pass_control(self, session, primary_address, secondary_address): + """Tell the GPIB device at the specified address to become controller in charge (CIC). + + Corresponds to viGpibPassControl function of the VISA library. + + :param session: Unique logical identifier to a session. + :param primary_address: Primary address of the GPIB device to which you want to pass control. + :param secondary_address: 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. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def gpib_send_ifc(self, session): + """Pulse the interface clear line (IFC) for at least 100 microseconds. + + Corresponds to viGpibSendIFC function of the VISA library. + + :param session: Unique logical identifier to a session. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def in_8(self, 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. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from memory, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def in_16(self, 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. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from memory, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def in_32(self, 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. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from memory, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def in_64(self, 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. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from memory, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def install_handler(self, session, event_type, handler, user_handle): + """Installs handlers for event callbacks. + + Corresponds to viInstallHandler function of the VISA library. + + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param handler: Interpreted as a valid reference to a handler to be installed by a client application. + :param user_handle: A value specified by an application that can be used for identifying handlers + uniquely for an event type. + :returns: a handler descriptor which consists of three elements: + - handler (a python callable) + - user handle (a ctypes object) + - ctypes handler (ctypes object wrapping handler) + and return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def list_resources(self, session, query='?*::INSTR'): + """Returns a tuple of all connected devices matching query. + + :param query: regular expression used to match devices. + """ + raise NotImplementedError + + def lock(self, session, lock_type, timeout, requested_key=None): + """Establishes an access mode to the specified resources. + + Corresponds to viLock function of the VISA library. + + :param session: Unique logical identifier to a session. + :param lock_type: Specifies the type of lock requested, either Constants.EXCLUSIVE_LOCK or Constants.SHARED_LOCK. + :param timeout: Absolute time period (in milliseconds) that a resource waits to get unlocked by the + locking session before returning an error. + :param requested_key: This parameter is not used and should be set to VI_NULL when lockType is VI_EXCLUSIVE_LOCK. + :return: access_key that can then be passed to other sessions to share the lock, return value of the library call. + :rtype: str, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def map_address(self, 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. + + :param session: Unique logical identifier to a session. + :param map_space: Specifies the address space to map. (Constants.*SPACE*) + :param map_base: Offset (in bytes) of the memory to be mapped. + :param map_size: Amount of memory to map (in bytes). + :param access: + :param suggested: If not Constants.VI_NULL (0), the operating system attempts to map the memory to the address + specified in suggested. 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 + suggested. + + :return: address in your process space where the memory was mapped, return value of the library call. + :rtype: address, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def map_trigger(self, 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. + + :param session: Unique logical identifier to a session. + :param trigger_source: Source line from which to map. (Constants.VI_TRIG*) + :param trigger_destination: Destination line to which to map. (Constants.VI_TRIG*) + :param mode: + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def memory_allocation(self, session, size, extended=False): + """Allocates memory from a resource's memory region. + + Corresponds to viMemAlloc* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param size: Specifies the size of the allocation. + :param extended: Use 64 bits offset independent of the platform. + :return: offset of the allocated memory, return value of the library call. + :rtype: offset, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def memory_free(self, session, offset, extended=False): + """Frees memory previously allocated using the memory_allocation() operation. + + Corresponds to viMemFree* function of the VISA library. + + :param session: Unique logical identifier to a session. + :param offset: Offset of the memory to free. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def move(self, 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. + + :param session: Unique logical identifier to a session. + :param source_space: Specifies the address space of the source. + :param source_offset: Offset of the starting address or register from which to read. + :param source_width: Specifies the data width of the source. + :param destination_space: Specifies the address space of the destination. + :param destination_offset: Offset of the starting address or register to which to write. + :param destination_width: Specifies the data width of the destination. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def move_asynchronously(self, 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. + + :param session: Unique logical identifier to a session. + :param source_space: Specifies the address space of the source. + :param source_offset: Offset of the starting address or register from which to read. + :param source_width: Specifies the data width of the source. + :param destination_space: Specifies the address space of the destination. + :param destination_offset: Offset of the starting address or register to which to write. + :param destination_width: Specifies the data width of the destination. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :return: Job identifier of this asynchronous move operation, return value of the library call. + :rtype: jobid, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def move_in_8(self, session, space, offset, length, extended=False): + """Moves an 8-bit block of data from the specified address space and offset to local memory. + + Corresponds to viMoveIn8* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from the bus, return value of the library call. + :rtype: list, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def move_in_16(self, session, space, offset, length, extended=False): + """Moves an 16-bit block of data from the specified address space and offset to local memory. + + Corresponds to viMoveIn16* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from the bus, return value of the library call. + :rtype: list, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def move_in_32(self, session, space, offset, length, extended=False): + """Moves an 32-bit block of data from the specified address space and offset to local memory. + + Corresponds to viMoveIn32* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from the bus, return value of the library call. + :rtype: list, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def move_in_64(self, session, space, offset, length, extended=False): + """Moves an 64-bit block of data from the specified address space and offset to local memory. + + Corresponds to viMoveIn64* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from the bus, return value of the library call. + :rtype: list, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def move_out_8(self, session, space, offset, length, data, extended=False): + """Moves an 8-bit block of data from local memory to the specified address space and offset. + + Corresponds to viMoveOut8* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + + Corresponds to viMoveOut8 function of the VISA library. + """ + raise NotImplementedError + + def move_out_16(self, session, space, offset, length, data, extended=False): + """Moves an 16-bit block of data from local memory to the specified address space and offset. + + Corresponds to viMoveOut16* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def move_out_32(self, session, space, offset, length, data, extended=False): + """Moves an 32-bit block of data from local memory to the specified address space and offset. + + Corresponds to viMoveOut32* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def move_out_64(self, session, space, offset, length, data, extended=False): + """Moves an 64-bit block of data from local memory to the specified address space and offset. + + Corresponds to viMoveOut64* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def open(self, 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. + + :param session: Resource Manager session (should always be a session returned from open_default_resource_manager()). + :param resource_name: Unique symbolic name of a resource. + :param access_mode: Specifies the mode by which the resource is to be accessed. + :type access_mode: :class:`pyvisa.constants.AccessModes` + :param open_timeout: Specifies the maximum time period (in milliseconds) that this operation waits + before returning an error. + :return: Unique logical identifier reference to a session, return value of the library call. + :rtype: session, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def open_default_resource_manager(self): + """This function returns a session to the Default Resource Manager resource. + + Corresponds to viOpenDefaultRM function of the VISA library. + + :return: Unique logical identifier to a Default Resource Manager session, return value of the library call. + :rtype: session, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def out_8(self, session, space, offset, data, extended=False): + """Write in an 8-bit value from the specified memory space and offset. + + Corresponds to viOut8* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def out_16(self, session, space, offset, data, extended=False): + """Write in an 16-bit value from the specified memory space and offset. + + Corresponds to viOut16* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def out_32(self, session, space, offset, data, extended=False): + """Write in an 32-bit value from the specified memory space and offset. + + Corresponds to viOut32* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def out_64(self, session, space, offset, data, extended=False): + """Write in an 64-bit value from the specified memory space and offset. + + Corresponds to viOut64* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def parse_resource(self, session, resource_name): + """Parse a resource string to get the interface information. + + Corresponds to viParseRsrc function of the VISA library. + + :param session: Resource Manager session (should always be the Default Resource Manager for VISA + returned from open_default_resource_manager()). + :param resource_name: Unique symbolic name of a resource. + :return: Resource information with interface type and board number, return value of the library call. + :rtype: :class:`pyvisa.highlevel.ResourceInfo`, :class:`pyvisa.constants.StatusCode` + """ + return self.parse_resource_extended(session, resource_name) + + def parse_resource_extended(self, session, resource_name): + """Parse a resource string to get extended interface information. + + Corresponds to viParseRsrcEx function of the VISA library. + + :param session: Resource Manager session (should always be the Default Resource Manager for VISA + returned from open_default_resource_manager()). + :param resource_name: Unique symbolic name of a resource. + :return: Resource information, return value of the library call. + :rtype: :class:`pyvisa.highlevel.ResourceInfo`, :class:`pyvisa.constants.StatusCode` + """ + try: + parsed = rname.parse_resource_name(resource_name) + + return (ResourceInfo(parsed.interface_type_const, + parsed.board, + parsed.resource_class, None, None), + constants.StatusCode.success) + except ValueError: + return 0, constants.StatusCode.error_invalid_resource_name + + def peek_8(self, session, address): + """Read an 8-bit value from the specified address. + + Corresponds to viPeek8 function of the VISA library. + + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :return: Data read from bus, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def peek_16(self, session, address): + """Read an 16-bit value from the specified address. + + Corresponds to viPeek16 function of the VISA library. + + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :return: Data read from bus, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def peek_32(self, session, address): + """Read an 32-bit value from the specified address. + + Corresponds to viPeek32 function of the VISA library. + + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :return: Data read from bus, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def peek_64(self, session, address): + """Read an 64-bit value from the specified address. + + Corresponds to viPeek64 function of the VISA library. + + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :return: Data read from bus, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def poke_8(self, session, address, data): + """Write an 8-bit value from the specified address. + + Corresponds to viPoke8 function of the VISA library. + + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param data: value to be written to the bus. + :return: Data read from bus. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def poke_16(self, session, address, data): + """Write an 16-bit value from the specified address. + + Corresponds to viPoke16 function of the VISA library. + + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param data: value to be written to the bus. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def poke_32(self, session, address, data): + """Write an 32-bit value from the specified address. + + Corresponds to viPoke32 function of the VISA library. + + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param data: value to be written to the bus. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def poke_64(self, session, address, data): + """Write an 64-bit value from the specified address. + + Corresponds to viPoke64 function of the VISA library. + + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param data: value to be written to the bus. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def read(self, session, count): + """Reads data from device or interface synchronously. + + Corresponds to viRead function of the VISA library. + + :param session: Unique logical identifier to a session. + :param count: Number of bytes to be read. + :return: data read, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def read_asynchronously(self, session, count): + """Reads data from device or interface asynchronously. + + Corresponds to viReadAsync function of the VISA library. + + :param session: Unique logical identifier to a session. + :param count: Number of bytes to be read. + :return: result, jobid, return value of the library call. + :rtype: ctypes buffer, jobid, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def read_stb(self, session): + """Reads a status byte of the service request. + + Corresponds to viReadSTB function of the VISA library. + + :param session: Unique logical identifier to a session. + :return: Service request status byte, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def read_to_file(self, session, filename, count): + """Read data synchronously, and store the transferred data in a file. + + Corresponds to viReadToFile function of the VISA library. + + :param session: Unique logical identifier to a session. + :param filename: Name of file to which data will be written. + :param count: Number of bytes to be read. + :return: Number of bytes actually transferred, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def set_attribute(self, session, attribute, attribute_state): + """Sets the state of an attribute. + + Corresponds to viSetAttribute function of the VISA library. + + :param session: Unique logical identifier to a session. + :param attribute: Attribute for which the state is to be modified. (Attributes.*) + :param attribute_state: The state of the attribute to be set for the specified object. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def set_buffer(self, session, mask, size): + """Sets the size for the formatted I/O and/or low-level I/O communication buffer(s). + + Corresponds to viSetBuf function of the VISA library. + + :param session: Unique logical identifier to a session. + :param mask: Specifies the type of buffer. (Constants.VI_READ_BUF, .VI_WRITE_BUF, .VI_IO_IN_BUF, .VI_IO_OUT_BUF) + :param size: The size to be set for the specified buffer(s). + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def status_description(self, session, status): + """Returns a user-readable description of the status code passed to the operation. + + Corresponds to viStatusDesc function of the VISA library. + + :param session: Unique logical identifier to a session. + :param status: Status code to interpret. + :return: - The user-readable string interpretation of the status code passed to the operation, + - return value of the library call. + :rtype: - unicode (Py2) or str (Py3) + - :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def terminate(self, session, degree, job_id): + """Requests a VISA session to terminate normal execution of an operation. + + Corresponds to viTerminate function of the VISA library. + + :param session: Unique logical identifier to a session. + :param degree: Constants.NULL + :param job_id: Specifies an operation identifier. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def uninstall_handler(self, session, event_type, handler, user_handle=None): + """Uninstalls handlers for events. + + Corresponds to viUninstallHandler function of the VISA library. + + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param handler: Interpreted as a valid reference to a handler to be uninstalled by a client application. + :param user_handle: A value specified by an application that can be used for identifying handlers + uniquely in a session for an event. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def unlock(self, session): + """Relinquishes a lock for the specified resource. + + Corresponds to viUnlock function of the VISA library. + + :param session: Unique logical identifier to a session. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def unmap_address(self, session): + """Unmaps memory space previously mapped by map_address(). + + Corresponds to viUnmapAddress function of the VISA library. + + :param session: Unique logical identifier to a session. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def unmap_trigger(self, session, trigger_source, trigger_destination): + """Undo a previous map from the specified trigger source line to the specified destination line. + + Corresponds to viUnmapTrigger function of the VISA library. + + :param session: Unique logical identifier to a session. + :param trigger_source: Source line used in previous map. (Constants.VI_TRIG*) + :param trigger_destination: Destination line used in previous map. (Constants.VI_TRIG*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def usb_control_in(self, session, request_type_bitmap_field, request_id, request_value, + index, length=0): + """Performs a USB control pipe transfer from the device. + + Corresponds to viUsbControlIn function of the VISA library. + + :param session: Unique logical identifier to a session. + :param request_type_bitmap_field: bmRequestType parameter of the setup stage of a USB control transfer. + :param request_id: bRequest parameter of the setup stage of a USB control transfer. + :param request_value: wValue parameter of the setup stage of a USB control transfer. + :param index: wIndex parameter of the setup stage of a USB control transfer. + This is usually the index of the interface or endpoint. + :param length: 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. + :return: - The data buffer that receives the data from the optional data stage of the control transfer + - return value of the library call. + :rtype: - bytes + - :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def usb_control_out(self, session, request_type_bitmap_field, request_id, request_value, + index, data=""): + """Performs a USB control pipe transfer to the device. + + Corresponds to viUsbControlOut function of the VISA library. + + :param session: Unique logical identifier to a session. + :param request_type_bitmap_field: bmRequestType parameter of the setup stage of a USB control transfer. + :param request_id: bRequest parameter of the setup stage of a USB control transfer. + :param request_value: wValue parameter of the setup stage of a USB control transfer. + :param index: wIndex parameter of the setup stage of a USB control transfer. + This is usually the index of the interface or endpoint. + :param data: The data buffer that sends the data in the optional data stage of the control transfer. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def vxi_command_query(self, session, mode, command): + """Sends the device a miscellaneous command or query and/or retrieves the response to a previous query. + + Corresponds to viVxiCommandQuery function of the VISA library. + + :param session: Unique logical identifier to a session. + :param mode: Specifies whether to issue a command and/or retrieve a response. (Constants.VI_VXI_CMD*, .VI_VXI_RESP*) + :param command: The miscellaneous command to send. + :return: The response retrieved from the device, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def wait_on_event(self, session, in_event_type, timeout): + """Waits for an occurrence of the specified event for a given session. + + Corresponds to viWaitOnEvent function of the VISA library. + + :param session: Unique logical identifier to a session. + :param in_event_type: Logical identifier of the event(s) to wait for. + :param timeout: 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. + :return: - Logical identifier of the event actually received + - A handle specifying the unique occurrence of an event + - return value of the library call. + :rtype: - eventtype + - event + - :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def write(self, session, data): + """Writes data to device or interface synchronously. + + Corresponds to viWrite function of the VISA library. + + :param session: Unique logical identifier to a session. + :param data: data to be written. + :type data: str + :return: Number of bytes actually transferred, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def write_asynchronously(self, session, data): + """Writes data to device or interface asynchronously. + + Corresponds to viWriteAsync function of the VISA library. + + :param session: Unique logical identifier to a session. + :param data: data to be written. + :return: Job ID of this asynchronous write operation, return value of the library call. + :rtype: jobid, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def write_from_file(self, session, filename, count): + """Take data from a file and write it out synchronously. + + Corresponds to viWriteFromFile function of the VISA library. + + :param session: Unique logical identifier to a session. + :param filename: Name of file from which data will be read. + :param count: Number of bytes to be written. + :return: Number of bytes actually transferred, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + +def list_backends(): + """Return installed backends. + + Backends are installed python packages named pyvisa- where + is the name of the backend. + + :rtype: list + """ + return ['ni'] + [name for (loader, name, ispkg) in pkgutil.iter_modules() + if name.startswith('pyvisa-')] + + +#: Maps backend name to VisaLibraryBase derived class +#: dict[str, :class:`pyvisa.highlevel.VisaLibraryBase`] +_WRAPPERS = {} + + +def get_wrapper_class(backend_name): + """Return the WRAPPER_CLASS for a given backend. + + :rtype: pyvisa.highlevel.VisaLibraryBase + """ + try: + return _WRAPPERS[backend_name] + except KeyError: + if backend_name == 'ni': + from .ctwrapper import NIVisaLibrary + _WRAPPERS['ni'] = NIVisaLibrary + return NIVisaLibrary + + for pkgname in list_backends(): + if pkgname.endswith('-' + backend_name): + pkg = __import__(pkgname) + _WRAPPERS[backend_name] = cls = pkg.WRAPPER_CLASS + return cls + else: + raise ValueError('Wrapper not found: No package named pyvisa-%s' % backend_name) + + +def open_visa_library(specification): + """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. + """ + + try: + argument, wrapper = specification.split('@') + except ValueError: + argument = specification + wrapper = 'ni' + + 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 + + :param visa_library: VisaLibrary Instance, path of the VISA library or VisaLibrary spec string. + (if not given, the default for the platform will be used). + """ + + #: Maps (Interface Type, Resource Class) to Python class encapsulating that resource. + _resource_classes = dict() + + #: Session handler for the resource manager. + _session = None + + @classmethod + def register_resource_class(cls, interface_type, resource_class, python_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)) + cls._resource_classes[(interface_type, resource_class)] = python_class + + def __new__(cls, visa_library=''): + 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 + + logger.debug('Created ResourceManager with session %s', obj.session) + return obj + + @property + def session(self): + """Resource Manager session handle. + + :raises: :class:`pyvisa.errors.InvalidSession` if session is closed. + """ + if self._session is None: + raise errors.InvalidSession() + return self._session + + @session.setter + def session(self, value): + self._session = value + + def __str__(self): + return 'Resource Manager of %s' % self.visalib + + def __repr__(self): + return '' % self.visalib + + def __del__(self): + self.close() + + def ignore_warning(self, *warnings_constants): + """Ignoring warnings context manager for the current resource. + + :param warnings_constants: constants identifying the warnings to ignore. + """ + return self.visalib.ignore_warning(self.session, *warnings_constants) + + @property + def last_status(self): + """Last status code returned for an operation with this Resource Manager + + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return self.visalib.get_last_status_in_session(self.session) + + def close(self): + """Close the resource manager session. + """ + try: + logger.debug('Closing ResourceManager (session: %s)', self.session) + self.visalib.close(self.session) + self.session = None + self.visalib.resource_manager = None + except errors.InvalidSession: + pass + + def list_resources(self, query='?*::INSTR'): + """Returns a tuple of all connected devices matching query. + + :param query: regular expression used to match devices. + """ + + return self.visalib.list_resources(self.session, query) + + def list_resources_info(self, query='?*::INSTR'): + """Returns a dictionary mapping resource names to resource extended + information of all connected devices matching query. + + :param query: regular expression used to match devices. + :return: Mapping of resource name to ResourceInfo + :rtype: dict[str, :class:`pyvisa.highlevel.ResourceInfo`] + """ + + return dict((resource, self.resource_info(resource)) + for resource in self.list_resources(query)) + + def resource_info(self, resource_name, extended=True): + """Get the (extended) information of a particular resource. + + :param resource_name: Unique symbolic name of a resource. + + :rtype: :class:`pyvisa.highlevel.ResourceInfo` + """ + + 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, + access_mode=constants.AccessModes.no_lock, + open_timeout=constants.VI_TMO_IMMEDIATE): + """Open the specified resource without wrapping into a class + + :param resource_name: name or alias of the resource to open. + :param access_mode: access mode. + :type access_mode: :class:`pyvisa.constants.AccessModes` + :param open_timeout: time out to open. + + :return: Unique logical identifier reference to a session. + """ + return self.visalib.open(self.session, resource_name, access_mode, open_timeout) + + def open_resource(self, resource_name, + access_mode=constants.AccessModes.no_lock, + open_timeout=constants.VI_TMO_IMMEDIATE, + resource_pyclass=None, + **kwargs): + """Return an instrument for the resource name. + + :param resource_name: name or alias of the resource to open. + :param access_mode: access mode. + :type access_mode: :class:`pyvisa.constants.AccessModes` + :param open_timeout: time out to open. + :param resource_pyclass: resource python class to use to instantiate the Resource. + Defaults to None: select based on the resource name. + :param kwargs: keyword arguments to be used to change instrument attributes + after construction. + + :rtype: :class:`pyvisa.resources.Resource` + """ + + if resource_pyclass is None: + info = self.resource_info(resource_name, extended=True) + + try: + resource_pyclass = self._resource_classes[(info.interface_type, info.resource_class)] + 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) + + return res + + #: For backwards compatibility + get_instrument = open_resource diff --git a/pyvisa/resources/__init__.py b/pyvisa/resources/__init__.py new file mode 100644 index 0000000..a18b91c --- /dev/null +++ b/pyvisa/resources/__init__.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.resources + ~~~~~~~~~~~~~~~~ + + High level wrappers for resources. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +from .resource import Resource + +from .gpib import GPIBInterface +from .vxi import VXIBackplane +from .vxi import VXIInstrument + +from .messagebased import MessageBasedResource +from .gpib import GPIBInstrument +from .tcpip import TCPIPInstrument +from .tcpip import TCPIPSocket +from .serial import SerialInstrument +from .usb import USBRaw +from .usb import USBInstrument + +from .registerbased import RegisterBasedResource +from .firewire import FirewireInstrument +from .pxi import PXIMemory +from .pxi import PXIInstrument +from .vxi import VXIMemory + +__all__ = ['Resource', 'MessageBasedResource', 'RegisterBasedResource', + 'GPIBInterface', 'VXIBackplane', 'VXIInstrument', + 'GPIBInstrument', 'TCPIPInstrument', 'TCPIPSocket', 'SerialInstrument', 'USBRaw', 'USBInstrument', + 'FirewireInstrument', 'PXIMemory', 'PXIInstrument', 'VXIMemory'] diff --git a/pyvisa/resources/firewire.py b/pyvisa/resources/firewire.py new file mode 100644 index 0000000..3fd5502 --- /dev/null +++ b/pyvisa/resources/firewire.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.resources.vxi + ~~~~~~~~~~~~~~~~~~~~ + + High level wrapper for VXI resources. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +from .. import constants + +from .registerbased import RegisterBasedResource + + +@RegisterBasedResource.register(constants.InterfaceType.firewire, 'INSTR') +class FirewireInstrument(RegisterBasedResource): + """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`. + """ diff --git a/pyvisa/resources/gpib.py b/pyvisa/resources/gpib.py new file mode 100644 index 0000000..e601cdf --- /dev/null +++ b/pyvisa/resources/gpib.py @@ -0,0 +1,148 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.resources.gpib + ~~~~~~~~~~~~~~~~~~~~~ + + High level wrapper for GPIB resources. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import time + +from .. import constants +from .resource import Resource +from .messagebased import MessageBasedResource, ControlRenMixin + + +class _GPIBMixin(ControlRenMixin): + """Common attributes and methods of GPIB Instr and Interface. + """ + + def send_command(self, data): + """Write GPIB command bytes on the bus. + + Corresponds to viGpibCommand function of the VISA library. + + :param data: data tor write. + :type data: bytes + :return: Number of written bytes, return value of the library call. + :rtype: int, VISAStatus + """ + return self.visalib.gpib_command(self.session, data) + + def control_atn(self, mode): + """Specifies the state of the ATN line and the local active controller state. + + Corresponds to viGpibControlATN function of the VISA library. + + :param mode: Specifies the state of the ATN line and optionally the local active controller state. + (Constants.GPIB_ATN*) + :return: return value of the library call. + :rtype: VISAStatus + """ + return self.visalib.gpib_control_atn(self.session, mode) + + def pass_control(self, primary_address, secondary_address): + """Tell the GPIB device at the specified address to become controller in charge (CIC). + + Corresponds to viGpibPassControl function of the VISA library. + + :param primary_address: Primary address of the GPIB device to which you want to pass control. + :param secondary_address: 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. + :return: return value of the library call. + :rtype: VISAStatus + """ + return self.visalib.gpib_pass_control(self.session, primary_address, secondary_address) + + def send_ifc(self): + """Pulse the interface clear line (IFC) for at least 100 microseconds. + + Corresponds to viGpibSendIFC function of the VISA library. + + :return: return value of the library call. + :rtype: VISAStatus + """ + 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`. + """ + + def wait_for_srq(self, timeout=25000): + """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. + + :param timeout: the maximum waiting time in milliseconds. + Defaul: 25000 (milliseconds). + None means waiting forever if necessary. + """ + self.enable_event(constants.VI_EVENT_SERVICE_REQ, constants.VI_QUEUE) + + if timeout and not(0 <= timeout <= 4294967295): + raise ValueError("timeout value is invalid") + + starting_time = time.clock() + + while True: + if timeout is None: + adjusted_timeout = constants.VI_TMO_INFINITE + else: + adjusted_timeout = int((starting_time + timeout/1e3 - time.clock())*1e3) + if adjusted_timeout < 0: + adjusted_timeout = 0 + + self.wait_on_event(constants.VI_EVENT_SERVICE_REQ, adjusted_timeout) + if self.stb & 0x40: + break + + self.discard_events(constants.VI_EVENT_SERVICE_REQ, constants.VI_QUEUE) + + +@Resource.register(constants.InterfaceType.gpib, 'INTFC') +class GPIBInterface(_GPIBMixin, Resource): + """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`. + """ + + def group_execute_trigger(self, *resources): + + 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)) diff --git a/pyvisa/resources/messagebased.py b/pyvisa/resources/messagebased.py new file mode 100644 index 0000000..2bf22e6 --- /dev/null +++ b/pyvisa/resources/messagebased.py @@ -0,0 +1,545 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.resources.messagebased + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + High level wrapper for MessageBased Instruments. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import contextlib +import time +import warnings + +from .. import logger +from .. import constants +from .. import errors +from .. import util + +from .resource import Resource + + +class ValuesFormat(object): + """Options for reading values. + """ + __slots__ = ('is_binary', 'container', + 'datatype', 'is_big_endian', + 'converter', 'separator', 'header_fmt') + + def __init__(self): + self.is_binary = True + self.datatype = 'f' + self.is_big_endian = False + self.container = list + self.converter = 'f' + self.separator = ',' + self.header_fmt = 'ieee' + + def use_ascii(self, converter, separator, container=list): + self.converter = converter + self.separator = separator + self.container = container + self.is_binary = False + + def use_binary(self, datatype, is_big_endian, container=list, header_fmt='ieee'): + self.datatype = datatype + self.is_big_endian = is_big_endian + self.container = container + self.is_binary = True + self.header_fmt = header_fmt + + +class ControlRenMixin(object): + """Common controlt_ren method of some messaged based resources. + """ + # 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): + """Controls the state of the GPIB Remote Enable (REN) interface line, and optionally the remote/local + state of the device. + + Corresponds to viGpibControlREN function of the VISA library. + + :param mode: Specifies the state of the REN line and optionally the device remote/local state. + (Constants.GPIB_REN*) + :return: return value of the library call. + :rtype: VISAStatus + """ + return self.visalib.gpib_control_ren(self.session, mode) + + +class MessageBasedResource(Resource): + """Base class for resources that use message based communication. + """ + + CR = '\r' + LF = '\n' + + _read_termination = None + _write_termination = CR + LF + _encoding = 'ascii' + + chunk_size = 20 * 1024 + query_delay = 0.0 + + _values_format = None + + def __init__(self, *args, **kwargs): + self._values_format = ValuesFormat() + super(MessageBasedResource, self).__init__(*args, **kwargs) + + # This is done for backwards compatibility but will be removed in 1.7 + @property + def values_format(self): + return self._values_format + + @values_format.setter + def values_format(self, fmt): + self._values_format.is_binary = not (fmt & 0x01 == 0) + if fmt & 0x03 == 1: #single + self._values_format.datatype = 'f' + elif fmt & 0x03 == 3: #double: + self._values_format.datatype = 'd' + else: + raise ValueError("unknown data values fmt requested") + + self._values_format.is_big_endian = fmt & 0x04 + + #### + + @property + def ask_delay(self): + """An alias for query_delay kept for backwards compatibility. + """ + return self.query_delay + + @ask_delay.setter + def ask_delay(self, value): + self.query_delay = value + + @property + def encoding(self): + """Encoding used for read and write operations. + """ + return self._encoding + + @encoding.setter + def encoding(self, encoding): + _ = 'test encoding'.encode(encoding).decode(encoding) + self._encoding = encoding + + @property + def read_termination(self): + """Read termination character. + """ + return self._read_termination + + @read_termination.setter + def read_termination(self, value): + + 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.VI_ATTR_TERMCHAR, ord(last_char)) + self.set_visa_attribute(constants.VI_ATTR_TERMCHAR_EN, 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.VI_ATTR_TERMCHAR, ord(self.LF)) + self.set_visa_attribute(constants.VI_ATTR_TERMCHAR_EN, constants.VI_FALSE) + + self._read_termination = value + + @property + def write_termination(self): + """Writer termination character. + """ + return self._write_termination + + @write_termination.setter + def write_termination(self, value): + self._write_termination = value + + def write_raw(self, message): + """Write a byte message to the device. + + :param message: the message to be sent. + :type message: bytes + :return: number of bytes written. + :rtype: int + """ + return self.visalib.write(self.session, message) + + def write(self, message, termination=None, encoding=None): + """Write a string message to the device. + + The write_termination is always appended to it. + + :param message: the message to be sent. + :type message: unicode (Py2) or str (Py3) + :return: number of bytes written. + :rtype: int + """ + + 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, values, converter='f', separator=',', termination=None, encoding=None): + """Write a string message to the device followed by values in ascii format. + + The write_termination is always appended to it. + + :param message: the message to be sent. + :type message: unicode (Py2) or str (Py3) + :param values: data to be writen to the device. + :param converter: function used to convert each value. + String formatting codes are also accepted. + Defaults to str. + :type converter: callable | str + :param separator: a callable that split the str into individual elements. + If a str is given, data.split(separator) is used. + :type: separator: (collections.Iterable[T]) -> str | str + :return: number of bytes written. + :rtype: int + """ + + 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) + + message = message.encode(enco) + block + + if term: + message += term.encode(enco) + + count = self.write_raw(message) + + return count + + def write_binary_values(self, message, values, datatype='f', is_big_endian=False, termination=None, encoding=None): + """Write a string message to the device followed by values in binary format. + + The write_termination is always appended to it. + + :param message: the message to be sent. + :type message: unicode (Py2) or str (Py3) + :param values: data to be writen to the device. + :param datatype: the format string for a single element. See struct module. + :param is_big_endian: boolean indicating endianess. + :return: number of bytes written. + :rtype: int + """ + 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_ieee_block(values, datatype, is_big_endian) + + message = message.encode(enco) + block + + if term: + message += term.encode(enco) + + count = self.write_raw(message) + + return count + + def write_values(self, message, values, termination=None, encoding=None): + + vf = self.values_format + + if vf.is_binary: + return self.write_binary_values(message, values, vf.datatype, vf.is_big_endian, termination, encoding) + + return self.write_ascii_values(message, values, vf.converter, vf.separator, termination, encoding) + + def read_raw(self, size=None): + """Read the unmodified string sent from the instrument to the computer. + + In contrast to read(), no termination characters are stripped. + + :rtype: bytes + """ + size = self.chunk_size if size is None else size + + loop_status = constants.StatusCode.success_max_count_read + + ret = bytes() + with self.ignore_warning(constants.VI_SUCCESS_DEV_NPRESENT, constants.VI_SUCCESS_MAX_CNT): + 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 += chunk + except errors.VisaIOError as e: + logger.debug('%s - exception while reading: %s', self._resource_name, e) + raise + + return ret + + def read(self, termination=None, encoding=None): + """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. + + All line-ending characters are stripped from the end of the string. + + :rtype: str + """ + 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[:-len(termination)] + + def read_values(self, fmt=None, container=list): + """Read a list of floating point values from the device. + + :param fmt: the format of the values. If given, it overrides + the class attribute "values_format". Possible values are bitwise + disjunctions of the above constants ascii, single, double, and + big_endian. Default is ascii. + :param container: the output datatype + + :return: the list of read values + :rtype: list + """ + if not fmt: + vf = self.values_format + if not vf.is_binary: + return util.from_ascii_block(self.read(), container) + data = self.read_raw() + try: + return util.parse_binary(data, vf.is_big_endian, vf.datatype=='f') + except ValueError as e: + try: + msg = e.args[0] + except IndexError: + msg = '' + raise errors.InvalidBinaryFormat(msg) + + if fmt & 0x01 == 0: # ascii + return util.from_ascii_block(self.read()) + + data = self.read_raw() + + try: + if fmt & 0x03 == 1: #single + is_single = True + elif fmt & 0x03 == 3: #double: + is_single = False + else: + raise ValueError("unknown data values fmt requested") + + is_big_endian = fmt & 0x04 # big endian + return util.parse_binary(data, is_big_endian, is_single) + except ValueError as e: + raise errors.InvalidBinaryFormat(e.args) + + def query(self, message, delay=None): + """A combination of write(message) and read() + + :param message: the message to send. + :type message: str + :param delay: delay in seconds between write and read operations. + if None, defaults to self.query_delay + :returns: the answer from the device. + :rtype: str + """ + + self.write(message) + + delay = self.query_delay if delay is None else delay + + if delay > 0.0: + time.sleep(delay) + return self.read() + + # Kept for backwards compatibility. + ask = query + + def query_values(self, message, delay=None): + """Query the device for values returning an iterable of values. + + The datatype expected is obtained from `values_format` + + :param message: the message to send. + :type message: str + :param delay: delay in seconds between write and read operations. + if None, defaults to self.query_delay + :returns: the answer from the device. + :rtype: list + """ + vf = self.values_format + + if vf.is_binary: + return self.query_binary_values(message, vf.datatype, vf.is_big_endian, vf.container, delay, vf.header_fmt) + + return self.query_ascii_values(message, vf.converter, vf.separator, vf.container, delay) + + def query_ascii_values(self, message, converter='f', separator=',', container=list, delay=None): + """Query the device for values in ascii format returning an iterable of values. + + :param message: the message to send. + :type message: str + :param delay: delay in seconds between write and read operations. + if None, defaults to self.query_delay + :param converter: function used to convert each element. + Defaults to float + :type converter: callable + :param separator: a callable that split the str into individual elements. + If a str is given, data.split(separator) is used. + :type: separator: (str) -> collections.Iterable[int] | str + :param container: container type to use for the output data. + :returns: the answer from the device. + :rtype: list + """ + + self.write(message) + if delay is None: + delay = self.query_delay + if delay > 0.0: + time.sleep(delay) + + block = self.read() + + return util.from_ascii_block(block, converter, separator, container) + + def query_binary_values(self, message, datatype='f', is_big_endian=False, container=list, delay=None, header_fmt='ieee'): + """Converts an iterable of numbers into a block of data in the ieee format. + + :param message: the message to send to the instrument. + :param datatype: the format string for a single element. See struct module. + :param is_big_endian: boolean indicating endianess. + Defaults to False. + :param container: container type to use for the output data. + :param delay: delay in seconds between write and read operations. + if None, defaults to self.query_delay + :rtype: bytes + """ + + 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) + + block = self.read_raw() + + if header_fmt == 'ieee': + offset, data_length = util.parse_ieee_block_header(block) + expected_length = offset + data_length + + while len(block) < expected_length: + block += self.read_raw() + + try: + if header_fmt == 'ieee': + return util.from_ieee_block(block, datatype, is_big_endian, container) + elif header_fmt == 'empty': + return util.from_binary_block(block, 0, None, datatype, is_big_endian, container) + elif header_fmt == 'hp': + return util.from_binary_block(block, 4, None, datatype, is_big_endian, container) + except ValueError as e: + raise errors.InvalidBinaryFormat(e.args) + + def ask_for_values(self, message, fmt=None, delay=None): + """A combination of write(message) and read_values() + + :param message: the message to send. + :type message: str + :param delay: delay in seconds between write and read operations. + if None, defaults to self.query_delay + :returns: the answer from the device. + :rtype: list + """ + + self.write(message) + if delay is None: + delay = self.query_delay + if delay > 0.0: + time.sleep(delay) + return self.read_values(fmt) + + def assert_trigger(self): + """Sends a software trigger to the device. + """ + + self.visalib.assert_trigger(self.session, constants.VI_TRIG_PROT_DEFAULT) + + @property + def stb(self): + """Service request status register.""" + + return self.read_stb() + + def read_stb(self): + """Service request status register. + """ + value, retcode = self.visalib.read_stb(self.session) + return value + + @contextlib.contextmanager + def read_termination_context(self, new_termination): + term = self.get_visa_attribute(constants.VI_ATTR_TERMCHAR) + self.set_visa_attribute(constants.VI_ATTR_TERMCHAR, ord(new_termination[-1])) + yield + self.set_visa_attribute(constants.VI_ATTR_TERMCHAR, term) + + +# Rohde and Schwarz Device via Passport. Not sure which Resource should be. +MessageBasedResource.register(constants.InterfaceType.rsnrp, 'INSTR')(MessageBasedResource) diff --git a/pyvisa/resources/pxi.py b/pyvisa/resources/pxi.py new file mode 100644 index 0000000..cfaef6e --- /dev/null +++ b/pyvisa/resources/pxi.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.resources.pxi + ~~~~~~~~~~~~~~~~~~~~ + + High level wrapper for pxi resources. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +from .. import constants + +from .resource import Resource +from .registerbased import RegisterBasedResource + + +@Resource.register(constants.InterfaceType.pxi, 'INSTR') +class PXIInstrument(RegisterBasedResource): + """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`. + """ + + +@Resource.register(constants.InterfaceType.pxi, 'MEMACC') +class PXIMemory(RegisterBasedResource): + """Communicates with to devices of type PXI[interface]::MEMACC + + Do not instantiate directly, use :meth:`pyvisa.highlevel.ResourceManager.open_resource`. + """ diff --git a/pyvisa/resources/registerbased.py b/pyvisa/resources/registerbased.py new file mode 100644 index 0000000..2b5eb51 --- /dev/null +++ b/pyvisa/resources/registerbased.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.resources.registerbased + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + High level wrapper for RegisterBased Instruments. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +from .resource import Resource + + +class RegisterBasedResource(Resource): + """Base class for resources that use register based communication. + """ + + def read_memory(self, space, offset, width, extended=False): + """Reads in an 8-bit, 16-bit, 32-bit, or 64-bit value from the specified memory space and offset. + + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param width: Number of bits to read. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from memory. + + Corresponds to viIn* functions of the visa library. + """ + return self.visalib.read_memory(self.session, space, offset, width, extended) + + def write_memory(self, space, offset, data, width, extended=False): + """Write in an 8-bit, 16-bit, 32-bit, value to the specified memory space and offset. + + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param data: Data to write to bus. + :param width: Number of bits to read. + :param extended: Use 64 bits offset independent of the platform. + + Corresponds to viOut* functions of the visa library. + """ + return self.visalib.write_memory(self.session, space, offset, data, width, extended) + + def move_in(self, space, offset, length, width, extended=False): + """Moves a block of data to local memory from the specified address space and offset. + + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param width: Number of bits to read per element. + :param extended: Use 64 bits offset independent of the platform. + """ + return self.visalib.move_in(self.session, space, offset, length, width, extended) + + def move_out(self, space, offset, length, data, width, extended=False): + """Moves a block of data from local memory to the specified address space and offset. + + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param data: Data to write to bus. + :param width: Number of bits to read per element. + :param extended: Use 64 bits offset independent of the platform. + """ + return self.visalib.move_out(space, offset, length, data, width, extended) diff --git a/pyvisa/resources/resource.py b/pyvisa/resources/resource.py new file mode 100644 index 0000000..4d33e91 --- /dev/null +++ b/pyvisa/resources/resource.py @@ -0,0 +1,397 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.resources.resource + ~~~~~~~~~~~~~~~~~~~~~~~~~ + + High level wrapper for a Resource. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import contextlib +import copy +import math +import time + +from .. import constants +from .. import errors +from .. import logger +from .. import highlevel +from .. import attributes + + +class WaitResponse(object): + """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 be + recorded as None, otherwise it records the proper EventType enum. + """ + def __init__(self, event_type, context, ret, visalib, timed_out=False): + if event_type == 0: + self.event_type = None + else: + self.event_type = constants.EventType(event_type) + self.context = context + self.ret = ret + self._visalib = visalib + self.timed_out = timed_out + + def __del__(self): + if self.context != None: + self._visalib.close(self.context) + + +class Resource(object): + """Base class for resources. + + Do not instantiate directly, use :meth:`pyvisa.highlevel.ResourceManager.open_resource`. + + :param resource_manager: A resource manager instance. + :param resource_name: the VISA name for the resource (eg. "GPIB::10") + """ + + @classmethod + def register(cls, interface_type, resource_class): + def _internal(python_class): + highlevel.ResourceManager.register_resource_class(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 list and extended it. + attrs = copy.copy(getattr(python_class, 'visa_attributes_classes', [])) + + for attr in attributes.AttributesPerResource[(interface_type, resource_class)]: + attrs.append(attr) + if not hasattr(python_class, attr.py_name) and attr.py_name != '': + setattr(python_class, attr.py_name, attr()) + for attr in attributes.AttributesPerResource[attributes.AllSessionTypes]: + attrs.append(attr) + if not hasattr(python_class, attr.py_name) and attr.py_name != '': + setattr(python_class, attr.py_name, attr()) + + setattr(python_class, 'visa_attributes_classes', attrs) + return python_class + return _internal + + def __init__(self, resource_manager, resource_name): + self._resource_manager = resource_manager + self.visalib = self._resource_manager.visalib + 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 = None + + @property + def session(self): + """Resource session handle. + + :raises: :class:`pyvisa.errors.InvalidSession` if session is closed. + """ + if self._session is None: + raise errors.InvalidSession() + return self._session + + @session.setter + def session(self, value): + self._session = value + + def __del__(self): + self.close() + + def __str__(self): + return "%s at %s" % (self.__class__.__name__, self.resource_name) + + def __repr__(self): + return "<%r(%r)>" % (self.__class__.__name__, self.resource_name) + + @property + def last_status(self): + """Last status code for this session. + + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return self.visalib.get_last_status_in_session(self.session) + + def _cleanup_timeout(self, timeout): + 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 + + @property + def timeout(self): + """The timeout in milliseconds for all resource I/O operations. + + 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 + + """ + timeout = self.get_visa_attribute(constants.VI_ATTR_TMO_VALUE) + if timeout == constants.VI_TMO_INFINITE: + return float('+inf') + return timeout + + @timeout.setter + def timeout(self, timeout): + timeout = self._cleanup_timeout(timeout) + self.set_visa_attribute(constants.VI_ATTR_TMO_VALUE, timeout) + + @timeout.deleter + def timeout(self): + self.set_visa_attribute(constants.VI_ATTR_TMO_VALUE, constants.VI_TMO_INFINITE) + + @property + def resource_info(self): + """Get the extended information of this resource. + + :param resource_name: Unique symbolic name of a resource. + + :rtype: :class:`pyvisa.highlevel.ResourceInfo` + """ + return self.visalib.parse_resource_extended(self._resource_manager.session, self.resource_name) + + @property + def interface_type(self): + """The interface type of the resource as a number. + """ + return self.visalib.parse_resource(self._resource_manager.session, + self.resource_name)[0].interface_type + + def ignore_warning(self, *warnings_constants): + """Ignoring warnings context manager for the current resource. + + :param warnings_constants: constants identifying the warnings to ignore. + """ + return self.visalib.ignore_warning(self.session, *warnings_constants) + + def open(self, access_mode=constants.AccessModes.no_lock, open_timeout=5000): + """Opens a session to the specified resource. + + :param access_mode: Specifies the mode by which the resource is to be accessed. + :type access_mode: :class:`pyvisa.constants.AccessModes` + :param open_timeout: Milliseconds before the open operation times out. + :type open_timeout: int + """ + + logger.debug('%s - opening ...', self._resource_name, extra=self._logging_extra) + with self._resource_manager.ignore_warning(constants.VI_SUCCESS_DEV_NPRESENT): + self.session, status = self._resource_manager.open_bare_resource(self._resource_name, access_mode, open_timeout) + + if status == constants.VI_SUCCESS_DEV_NPRESENT: + # 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.VI_ERROR_NLISTENERS: + 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): + """Called just before closing an instrument. + """ + self.__switch_events_off() + + def close(self): + """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) + self.session = None + except errors.InvalidSession: + pass + + def __switch_events_off(self): + self.disable_event(constants.VI_ALL_ENABLED_EVENTS, constants.VI_ALL_MECH) + self.discard_events(constants.VI_ALL_ENABLED_EVENTS, constants.VI_ALL_MECH) + self.visalib.uninstall_all_visa_handlers(self.session) + + def get_visa_attribute(self, name): + """Retrieves the state of an attribute in this resource. + + :param name: Resource attribute for which the state query is made (see Attributes.*) + :return: The state of the queried attribute for a specified resource. + :rtype: unicode (Py2) or str (Py3), list or other type + """ + return self.visalib.get_attribute(self.session, name)[0] + + def set_visa_attribute(self, name, state): + """Sets the state of an attribute. + + :param name: Attribute for which the state is to be modified. (Attributes.*) + :param state: The state of the attribute to be set for the specified object. + """ + self.visalib.set_attribute(self.session, name, state) + + def clear(self): + """Clears this resource + """ + self.visalib.clear(self.session) + + def install_handler(self, event_type, handler, user_handle=None): + """Installs handlers for event callbacks in this resource. + + :param event_type: Logical event identifier. + :param handler: Interpreted as a valid reference to a handler to be installed by a client application. + :param user_handle: A value specified by an application that can be used for identifying handlers + uniquely for an event type. + :returns: user handle (a ctypes object) + """ + + return self.visalib.install_visa_handler(self.session, event_type, handler, user_handle) + + def uninstall_handler(self, event_type, handler, user_handle=None): + """Uninstalls handlers for events in this resource. + + :param event_type: Logical event identifier. + :param handler: Interpreted as a valid reference to a handler to be uninstalled by a client application. + :param user_handle: The user handle (ctypes object or None) returned by install_handler. + """ + + self.visalib.uninstall_visa_handler(self.session, event_type, handler, user_handle) + + def disable_event(self, event_type, mechanism): + """Disables notification of the specified event type(s) via the specified mechanism(s). + + :param event_type: Logical event identifier. + :param mechanism: Specifies event handling mechanisms to be disabled. + (Constants.VI_QUEUE, .VI_HNDLR, .VI_SUSPEND_HNDLR, .VI_ALL_MECH) + """ + self.visalib.disable_event(self.session, event_type, mechanism) + + def discard_events(self, event_type, mechanism): + """Discards event occurrences for specified event types and mechanisms in this resource. + + :param event_type: Logical event identifier. + :param mechanism: Specifies event handling mechanisms to be dicarded. + (Constants.VI_QUEUE, .VI_HNDLR, .VI_SUSPEND_HNDLR, .VI_ALL_MECH) + """ + self.visalib.discard_events(self.session, event_type, mechanism) + + def enable_event(self, event_type, mechanism, context=None): + """Enable event occurrences for specified event types and mechanisms in this resource. + + :param event_type: Logical event identifier. + :param mechanism: Specifies event handling mechanisms to be enabled. + (Constants.VI_QUEUE, .VI_HNDLR, .VI_SUSPEND_HNDLR) + :param context: Not currently used, leave as None. + """ + self.visalib.enable_event(self.session, event_type, mechanism, context) + + def wait_on_event(self, in_event_type, timeout, capture_timeout=False): + """Waits for an occurrence of the specified event in this resource. + + :param in_event_type: Logical identifier of the event(s) to wait for. + :param timeout: 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. + :param capture_timeout: When True will not produce a VisaIOError(VI_ERROR_TMO) but + instead return a WaitResponse with timed_out=True + :return: A 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(0, None, exc.error_code, self.visalib, timed_out=True) + raise + return WaitResponse(event_type, context, ret, self.visalib) + + def lock(self, timeout='default', requested_key=None): + """Establish a shared lock to the resource. + + :param timeout: Absolute time period (in milliseconds) that a resource + waits to get unlocked by the locking session before + returning an error. (Defaults to self.timeout) + :param requested_key: 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: A new shared access key if requested_key is None, + otherwise, same value as the requested_key + """ + timeout = self.timeout if timeout == 'default' else timeout + timeout = self._cleanup_timeout(timeout) + return self.visalib.lock(self.session, constants.AccessModes.shared_lock, timeout, requested_key)[0] + + def lock_excl(self, timeout='default'): + """Establish an exclusive lock to the resource. + + :param timeout: Absolute time period (in milliseconds) that a resource + waits to get unlocked by the locking session before + returning an error. (Defaults to self.timeout) + """ + timeout = self.timeout if timeout == 'default' else timeout + timeout = self._cleanup_timeout(timeout) + self.visalib.lock(self.session, constants.AccessModes.exclusive_lock, timeout, None) + + def unlock(self): + """Relinquishes a lock for the specified resource. + """ + self.visalib.unlock(self.session) + + @contextlib.contextmanager + def lock_context(self, timeout='default', requested_key='exclusive'): + """A context that locks + + :param timeout: Absolute time period (in milliseconds) that a resource + waits to get unlocked by the locking session before + returning an error. (Defaults to self.timeout) + :param requested_key: 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. + The returned context is 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) diff --git a/pyvisa/resources/serial.py b/pyvisa/resources/serial.py new file mode 100644 index 0000000..0b32289 --- /dev/null +++ b/pyvisa/resources/serial.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.resources.serial + ~~~~~~~~~~~~~~~~~~~~~~~ + + High level wrapper for Serial resources. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +from .. import constants + +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`. + """ + + def flush(self, mask): + """Manually clears the specified buffers and cause the buffer data + to be written to the device. + + :param mask: Specifies the action to be taken with flushing the buffer. + (Constants.READ*, .WRITE*, .IO*) + """ + self.visalib.flush(self.session, mask) diff --git a/pyvisa/resources/tcpip.py b/pyvisa/resources/tcpip.py new file mode 100644 index 0000000..87f9fc6 --- /dev/null +++ b/pyvisa/resources/tcpip.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.resources.tcpip + ~~~~~~~~~~~~~~~~~~~~~~ + + High level wrapper for TCPIP resources. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +from .. import constants + +from .resource import Resource +from .messagebased import MessageBasedResource, ControlRenMixin + + +@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`. + """ + + +@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`. + """ diff --git a/pyvisa/resources/usb.py b/pyvisa/resources/usb.py new file mode 100644 index 0000000..21e5025 --- /dev/null +++ b/pyvisa/resources/usb.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.resources.usb + ~~~~~~~~~~~~~~~~~~~~ + + High level wrapper for USB resources. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +from .. import constants +from .messagebased import MessageBasedResource, ControlRenMixin + + +@MessageBasedResource.register(constants.InterfaceType.usb, 'INSTR') +class USBInstrument(ControlRenMixin, MessageBasedResource): + """Communicates with devices of type 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`. + """ + + def control_in(self, request_type_bitmap_field, request_id, request_value, index, length=0): + """Performs a USB control pipe transfer from the device. + + :param request_type_bitmap_field: bmRequestType parameter of the setup stage of a USB control transfer. + :param request_id: bRequest parameter of the setup stage of a USB control transfer. + :param request_value: wValue parameter of the setup stage of a USB control transfer. + :param index: wIndex parameter of the setup stage of a USB control transfer. + This is usually the index of the interface or endpoint. + :param length: 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. + :return: The data buffer that receives the data from the optional data stage of the control transfer. + :rtype: bytes + """ + return self.visalib.usb_control_in(self.session, request_type_bitmap_field, + request_id, request_value, index, length) + + def usb_control_out(self, request_type_bitmap_field, request_id, request_value, index, data=""): + """Performs a USB control pipe transfer to the device. + + :param request_type_bitmap_field: bmRequestType parameter of the setup stage of a USB control transfer. + :param request_id: bRequest parameter of the setup stage of a USB control transfer. + :param request_value: wValue parameter of the setup stage of a USB control transfer. + :param index: wIndex parameter of the setup stage of a USB control transfer. + This is usually the index of the interface or endpoint. + :param data: The data buffer that sends the data in the optional data stage of the control transfer. + """ + return self.visalib.usb_control_out(request_type_bitmap_field, request_id, request_value, index, data) + + +@MessageBasedResource.register(constants.InterfaceType.usb, 'RAW') +class USBRaw(MessageBasedResource): + """Communicates with to devices of type 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`. + """ diff --git a/pyvisa/resources/vxi.py b/pyvisa/resources/vxi.py new file mode 100644 index 0000000..e84e8a8 --- /dev/null +++ b/pyvisa/resources/vxi.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.resources.vxi + ~~~~~~~~~~~~~~~~~~~~ + + High level wrapper for VXI resources. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +from .. import constants + +from .resource import Resource +from .registerbased import RegisterBasedResource + + +@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`. + """ + + +@Resource.register(constants.InterfaceType.vxi, 'INSTR') +class VXIInstrument(Resource): + """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`. + """ + + +@Resource.register(constants.InterfaceType.vxi, 'MEMACC') +class VXIMemory(RegisterBasedResource): + """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`. + """ diff --git a/pyvisa/rname.py b/pyvisa/rname.py new file mode 100644 index 0000000..4cb1a58 --- /dev/null +++ b/pyvisa/rname.py @@ -0,0 +1,573 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.rname + ~~~~~~~~~~~~ + + Functions and classes to parse and assemble resource name. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import re +import contextlib +from collections import namedtuple, defaultdict + +from . import constants, errors, logger + +# :type: set[str] +_INTERFACE_TYPES = set() + +# Resource Class for Interface type +# :type: dict[str, set[str]] +_RESOURCE_CLASSES = defaultdict(set) + +# :type: dict[(str, str), ResourceName] +_SUBCLASSES = {} + +# DEFAULT Resource Class for a given interface type. +# :type: dict[str, str] +_DEFAULT_RC = {} + + +class InvalidResourceName(ValueError): + """Exception raised when the resource name cannot be parsed. + """ + + def __init__(self, msg): + self.msg = msg + + @classmethod + def bad_syntax(cls, syntax, resource_name, ex=None): + """Exception used 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, + resource_name=None): + """Exception used when the subclass for a given interface type / resource class pair + cannot be found. + """ + + msg = "Parser for not found (%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, resource_name=None): + """Exception used 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): + return self.msg + + +def register_subclass(cls): + """Register a subclass for a given interface type and resource class. + """ + + 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(object): + """Base class for ResourceNames to be used as a Mixin + """ + + # Interface type string + interface_type = '' + + # Resource class string + resource_class = '' + + # Specifices if the resource class part of the string is optional. + is_rc_optional = False + + # Formatting string for canonical + _canonical_fmt = '' + + # VISA syntax for resource + _visa_syntax = '' + + # Resource name provided by the user (not empty only when parsing) + user = '' + + @property + def interface_type_const(self): + try: + return getattr(constants.InterfaceType, self.interface_type.lower()) + except: + return constants.InterfaceType.unknown + + @classmethod + def from_string(cls, resource_name): + """Parse a resource name and return a ResourceName + + :type resource_name: str + :rtype: ResourceName + + :raises InvalidResourceName: 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 + + 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 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): + interface_type = kwargs.pop('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: + return subclass(**kwargs) + except ValueError as ex: + raise InvalidResourceName(str(ex)) + + def __str__(self): + return self._canonical_fmt.format(self) + + +def build_rn_class(interface_type, resource_parts, resource_class, + is_rc_optional=True): + """Builds a resource name class by mixing a named tuple and ResourceName. + + It also registers the class. + + The field names are changed to lower case and the spaces replaced + by underscores ('_'). + + :param interface_type: the interface type + :type: interface_type: str + :param resource_parts: each of the parts of the resource name indicating + name and default value. + Use None for mandatory fields. + :type resource_parts: tuple[(str, str)] + :param resource_class: the resource class + :type resource_class: str + :param is_rc_optional: indicates if the resource class part is optional + :type is_rc_optional: boolean. + """ + + interface_type = interface_type.upper() + resource_class = resource_class.upper() + + syntax = interface_type + fmt = interface_type + fields = [] + + # Contains the resource parts but using python friendly names + # (all lower case and replacing spaces by underscores) + p_resource_parts = [] + + kwdoc = [] + + # Assemble the syntax and format string based on the resource parts + for ndx, (name, default_value) in enumerate(resource_parts): + pname = name.lower().replace(' ', '_') + fields.append(pname) + p_resource_parts.append((pname, default_value)) + + sep = '::' if ndx else '' + + fmt += sep + '{0.%s}' % pname + + if default_value is None: + syntax += sep + name + else: + syntax += '[' + sep + name + ']' + + kwdoc.append('- %s (%s)' % (pname, 'required' if default_value is None + else default_value)) + + fmt += '::' + resource_class + + if not is_rc_optional: + syntax += '::' + resource_class + else: + syntax += '[' + '::' + resource_class + ']' + + class _C(namedtuple('Internal', ' '.join(fields)), ResourceName): + """%s %s" + + Can be created with the following keyword only arguments: + %s + + Format : + %s + """ % (resource_class, interface_type, ' \n'.join(kwdoc), syntax) + + def __new__(cls, **kwargs): + new_kwargs = dict(p_resource_parts, **kwargs) + + for key, value in new_kwargs.items(): + if value is None: + raise ValueError(key + ' is a required parameter') + + return super(_C, cls).__new__(cls, **new_kwargs) + + @classmethod + def from_parts(cls, *parts): + + if len(parts) < sum(1 for _, v in p_resource_parts + if v is not None): + raise ValueError('not enough parts') + elif len(parts) > len(p_resource_parts): + raise ValueError('too many parts') + + (k, default), rp = p_resource_parts[0], p_resource_parts[1:] + + # The first part (just after the interface_type) is the only + # optional part which can be and empty and therefore the + # default value should be used. + p, pending = parts[0], parts[1:] + kwargs = {k: default if p == '' else p} + + # The rest of the parts are consumed when mandatory elements are required. + while len(pending) < len(rp): + (k, default), rp = rp[0], rp[1:] + if default is None: + if not parts: + raise ValueError(k + ' part is mandatory') + p, pending = pending[0], pending[1:] + if not p: + raise ValueError(k + ' part is mandatory') + kwargs[k] = p + else: + kwargs[k] = default + + # When the length of the pending provided and resource parts + # are equal, we just consume everything. + kwargs.update((k, p) for (k, v), p in zip(rp, pending)) + + return cls(**kwargs) + + _C.interface_type = interface_type + _C.resource_class = resource_class + _C.is_rc_optional = is_rc_optional + _C._canonical_fmt = fmt + _C._visa_syntax = syntax + + _C.__name__ = str(interface_type + resource_class.title()) + + return register_subclass(_C) + +# Build subclasses for each resource + +GPIBInstr = build_rn_class('GPIB', + (('board', '0'), ('primary address', None), + ('secondary address', constants.VI_NO_SEC_ADDR)), + 'INSTR') + +GPIBIntfc = build_rn_class('GPIB', (('board', '0'), ), 'INTFC', False) + +ASRLInstr = build_rn_class('ASRL', (('board', '0'), ), 'INSTR') + +TCPIPInstr = build_rn_class('TCPIP', (('board', '0'), ('host address', None), + ('LAN device name', 'inst0'), ), 'INSTR') + +TCPIPSocket = build_rn_class('TCPIP', (('board', '0'), ('host address', None), + ('port', None), ), 'SOCKET', False) + +USBInstr = build_rn_class('USB', + (('board', '0'), ('manufacturer ID', None), + ('model code', None), ('serial number', None), + ('USB interface number', '0')), 'INSTR') + +USBRaw = build_rn_class('USB', (('board', '0'), ('manufacturer ID', None), + ('model code', None), ('serial number', None), + ('USB interface number', '0')), 'RAW', False) + +PXIBackplane = build_rn_class('PXI', (('interface', '0'), + ('chassis number', None)), 'BACKPLANE', + False) + +PXIMemacc = build_rn_class('PXI', (('interface', '0'), ), 'MEMACC', False) + +VXIBackplane = build_rn_class('VXI', (('board', '0'), + ('VXI logical address', '0')), + 'BACKPLANE', False) + +VXIInstr = build_rn_class('VXI', (('board', '0'), + ('VXI logical address', None)), 'INSTR', + True) + +VXIMemacc = build_rn_class('VXI', (('board', '0'), ), 'MEMACC', False) + +VXIServant = build_rn_class('VXI', (('board', '0'), ), 'SERVANT', False) + +# TODO 3 types of PXI INSTR +# TODO ENET-Serial INSTR +# TODO Remote NI-VISA + + +def assemble_canonical_name(**kwargs): + """Given a set of keyword arguments defining a resource name, + return the canonical resource name. + """ + return str(ResourceName.from_kwargs(**kwargs)) + + +def to_canonical_name(resource_name): + """Parse a resource name and return the canonical version. + + :type resource_name: str + :rtype: str + """ + return str(ResourceName.from_string(resource_name)) + + +parse_resource_name = ResourceName.from_string + + +def filter(resources, query): + """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. + + + :param resources: iterable of resources. + :param query: query expression. + """ + + 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)) + + +def filter2(resources, query, open_resource): + """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. + + :param resources: iterable of resources. + :param query: query expression. + :param open_resource: function to open the resource. + """ + + 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 filtered + + optional = optional.replace('&&', 'and').replace('||', 'or').replace('!', 'not ') + optional = optional.replace('VI_', 'res.VI_') + + class AttrGetter(): + + def __init__(self, resource_name): + self.resource_name = resource_name + self.parsed = parse_resource_name(resource_name) + self.resource = None + + def __getattr__(self, item): + if item == 'VI_ATTR_INTF_NUM': + return int(self.parsed.board) + elif item == 'VI_ATTR_MANF_ID': + return self.parsed.manufacturer_id + elif item == 'VI_ATTR_MODEL_CODE': + return self.parsed.model_code + elif item == 'VI_ATTR_USB_SERIAL_NUM': + return self.parsed.serial_number + elif item == 'VI_ATTR_USB_INTFC_NUM': + return int(self.parsed.board) + elif item == 'VI_ATTR_TCPIP_ADDR': + return self.parsed.host_address + elif item == 'VI_ATTR_TCPIP_DEVICE_NAME': + return self.parsed.lan_device_name + elif item == 'VI_ATTR_TCPIP_PORT': + return int(self.parsed.port) + elif item == 'VI_ATTR_INTF_NUM': + return int(self.parsed.board) + elif item == 'VI_ATTR_GPIB_PRIMARY_ADDR': + return int(self.parsed.primary_address) + elif item == 'VI_ATTR_GPIB_SECONDARY_ADDR': + return int(self.parsed.secondary_address) + elif item == 'VI_ATTR_PXI_CHASSIS': + return self.parsed.chassis_number + elif item == 'VI_ATTR_MAINFRAME_LA': + return self.parsed.vxi_logical_address + + if self.resource is None: + self.resource = open_resource(self.resource_name) + + return self.resource.get_visa_attribute(item) + + @contextlib.contextmanager + def open_close(resource_name): + getter = AttrGetter(resource_name) + yield getter + if getter.resource is not None: + getter.resource.close() + + selected = [] + for rn in filtered: + with open_close(rn) as getter: + if eval(optional, None, dict(res=getter)): + selected.append(rn) + + + diff --git a/pyvisa/shell.py b/pyvisa/shell.py new file mode 100644 index 0000000..ef2175d --- /dev/null +++ b/pyvisa/shell.py @@ -0,0 +1,327 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- +""" + pyvisa.shell + ~~~~~~~~~~~~ + + Shell for interactive testing. + + This file is taken from the Lantz Project. + + :copyright: (c) 2014 by PyVISA Authors, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import cmd +import sys + +from .compat import input +from . import ResourceManager, constants, VisaIOError +from .thirdparty import prettytable + +if sys.platform == 'darwin': + + class Cmd(cmd.Cmd): + + # This has been patched to enable autocompletion on Mac OSX + def cmdloop(self, intro=None): + """Repeatedly issue a prompt, accept input, parse an initial prefix + off the received input, and dispatch to action methods, passing them + the remainder of the line as argument. + """ + + self.preloop() + if self.use_rawinput and self.completekey: + try: + import readline + self.old_completer = readline.get_completer() + readline.set_completer(self.complete) + + if 'libedit' in readline.__doc__: + # readline linked to BSD libedit + if self.completekey == 'tab': + key = '^I' + else: + key = self.completekey + readline.parse_and_bind('bind %s rl_complete' % (key,)) + else: + # readline linked to the real readline + readline.parse_and_bind(self.completekey + ': complete') + + except ImportError: + pass + try: + if intro is not None: + self.intro = intro + if self.intro: + self.stdout.write(str(self.intro)+"\n") + stop = None + while not stop: + if self.cmdqueue: + line = self.cmdqueue.pop(0) + else: + if self.use_rawinput: + try: + line = input(self.prompt) + except EOFError: + line = 'EOF' + else: + self.stdout.write(self.prompt) + self.stdout.flush() + line = self.stdin.readline() + if not len(line): + line = 'EOF' + else: + line = line.rstrip('\r\n') + line = self.precmd(line) + stop = self.onecmd(line) + stop = self.postcmd(stop, line) + self.postloop() + finally: + if self.use_rawinput and self.completekey: + try: + import readline + readline.set_completer(self.old_completer) + except ImportError: + pass +else: + Cmd = cmd.Cmd + + +class VisaShell(Cmd): + """Shell for interactive testing. + """ + + intro = '\nWelcome to the VISA shell. Type help or ? to list commands.\n' + prompt = '(visa) ' + + use_rawinput = True + + def __init__(self, library_path=''): + Cmd.__init__(self) + 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. + #: list[tuple(str, str)] + self.resources = [] + + #: Resource in use + #: pyvisa.resources.Resource + self.current = None + + #: list[str] + self.py_attr = [] + #: list[str] + self.vi_attr = [] + + 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('({:2d}) {}'.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): + 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 print_attribute_list(self): + 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): + """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') + elif len(args) == 1: + # Get + 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) + else: + attr_name, attr_state = args[0], args[1] + if attr_name.startswith('VI_'): + try: + self.current.set_visa_attribute(getattr(constants, attr_name), attr_state) + print('Done') + except Exception as e: + print(e) + else: + print('Setting Resource Attributes by python name is not yet supported.') + return + try: + print(getattr(self.current, attr_name)) + print('Done') + except Exception as e: + print(e) + + def complete_attr(self, text, line, begidx, endidx): + 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_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): + """. + """ + return True + + +def main(library_path=''): + VisaShell(library_path).cmdloop() + diff --git a/pyvisa/testsuite/__init__.py b/pyvisa/testsuite/__init__.py new file mode 100644 index 0000000..e46a262 --- /dev/null +++ b/pyvisa/testsuite/__init__.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- + +from __future__ import division, unicode_literals, print_function, absolute_import + +import os +import logging +from contextlib import contextmanager + +from logging.handlers import BufferingHandler + +from pyvisa import logger +from pyvisa.compat import unittest + + +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(unittest.TestCase): + + CHECK_NO_WARNING = True + + @contextmanager + def capture_log(self, level=logging.DEBUG): + th = TestHandler() + th.setLevel(level) + logger.addHandler(th) + if self._test_handler is None: + yield th.buffer + else: + l = len(self._test_handler.buffer) + yield th.buffer + self._test_handler.buffer = self._test_handler.buffer[:l] + + def setUp(self): + self._test_handler = None + if self.CHECK_NO_WARNING: + self._test_handler = th = TestHandler() + th.setLevel(logging.WARNING) + logger.addHandler(th) + + def tearDown(self): + if self._test_handler is not None: + buf = self._test_handler.buffer + l = len(buf) + msg = '\n'.join(record.get('msg', str(record)) for record in buf) + self.assertEqual(l, 0, msg='%d warnings raised.\n%s' % (l, msg)) + + +def testsuite(): + """A testsuite that has all the pyvisa tests. + """ + return unittest.TestLoader().discover(os.path.dirname(__file__)) + + +def main(): + """Runs the testsuite as command line application. + """ + try: + unittest.main() + except Exception as e: + print('Error: %s' % e) + + +def run(): + """Run all tests. + + :return: a :class:`unittest.TestResult` object + """ + test_runner = unittest.TextTestRunner() + return test_runner.run(testsuite()) + diff --git a/pyvisa/testsuite/test_rname.py b/pyvisa/testsuite/test_rname.py new file mode 100644 index 0000000..f6c694b --- /dev/null +++ b/pyvisa/testsuite/test_rname.py @@ -0,0 +1,256 @@ +# -*- coding: utf-8 -*- + +from __future__ import division, unicode_literals, print_function, absolute_import + +from pyvisa.compat import unittest +from pyvisa.testsuite import BaseTestCase + +from pyvisa import rname + +parse = rname.ResourceName.from_string + + +class TestParsers(BaseTestCase): + + def _parse_test(self, rn, **kwargs): + p = parse(rn) + r = dict((k, getattr(p, k)) for k in p._fields + ('interface_type', 'resource_class')) + r['canonical_resource_name'] = str(p) + self.assertEqual(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::0::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('GPIB::1::INSTR', + interface_type='GPIB', + resource_class='INSTR', + board='0', + primary_address='1', + secondary_address=65535, + canonical_resource_name='GPIB0::1::65535::INSTR') + + self._parse_test('GPIB1::1::INSTR', + interface_type='GPIB', + resource_class='INSTR', + board='1', + primary_address='1', + secondary_address=65535, + canonical_resource_name='GPIB1::1::65535::INSTR') + + self._parse_test('GPIB1::1', + interface_type='GPIB', + resource_class='INSTR', + board='1', + primary_address='1', + secondary_address=65535, + canonical_resource_name='GPIB1::1::65535::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): + + run_list = ( + 'GPIB0::8::65535::INSTR', + 'TCPIP0::localhost:1111::inst0::INSTR', + 'ASRL1::INSTR', + 'USB0::0x1111::0x2222::0x4445::0::RAW', + 'USB0::0x1111::0x2222::0x1234::0::INSTR', + 'TCPIP0::localhost::10001::SOCKET', + 'GPIB9::8::65535::INSTR', + 'ASRL11::INSTR', + 'ASRL2::INSTR' + ) + + def _test_filter(self, expr, *correct): + ok = tuple(self.run_list[n] for n in correct) + self.assertEqual(rname.filter(self.run_list, expr), ok) + + def test_filter(self): + self._test_filter('?*::INSTR', 0, 1, 2, 4, 6, 7, 8) + self._test_filter('GPIB?+INSTR', 0, 6) + self._test_filter('GPIB[0-8]*::?*INSTR', 0) + self._test_filter('GPIB[^0]::?*INSTR', 6) + self._test_filter('ASRL1+::INSTR', 2, 7) + self._test_filter('(GPIB|VXI)?*INSTR', 0, 6) + self._test_filter('?*', *tuple(range(len(self.run_list)))) diff --git a/pyvisa/testsuite/test_util.py b/pyvisa/testsuite/test_util.py new file mode 100644 index 0000000..85ff8c7 --- /dev/null +++ b/pyvisa/testsuite/test_util.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- + +from __future__ import division, unicode_literals, print_function, absolute_import + +from pyvisa.testsuite import BaseTestCase + +from pyvisa import util + +try: + # noinspection PyPackageRequirements + import numpy as np +except ImportError: + np = None + +class TestParser(BaseTestCase): + + def test_parse_binary(self): + s = b'#A@\xe2\x8b<@\xe2\x8b<@\xe2\x8b<@\xe2\x8b<@\xde\x8b<@\xde\x8b<@\xde\x8b<' \ + b'@\xde\x8b<@\xe0\x8b<@\xe0\x8b<@\xdc\x8b<@\xde\x8b<@\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] + p = util.parse_binary(s, is_big_endian=False, is_single=True) + for a, b in zip(p, e): + self.assertAlmostEqual(a, b) + p = util.from_ieee_block(s, datatype='f', is_big_endian=False) + for a, b in zip(p, e): + self.assertAlmostEqual(a, b) + + def test_ieee_integer(self): + values = list(range(99)) + containers = (list, tuple) #+ ((np.asarray,) if np else ()) + for fmt in 'bBhHiIfd': + for endi in (True, False): + for cont in containers: + conv = cont(values) + msg = 'fmt=%s, endianness=%s, container=%s' % (fmt, endi, cont.__name__) + try: + block = util.to_ieee_block(conv, fmt, endi) + parsed = util.from_ieee_block(block, fmt, endi, cont) + except Exception as e: + raise Exception(msg + '\n' + repr(e)) + + self.assertEqual(conv, parsed, msg) + + def test_ieee_noninteger(self): + values = [val + 0.5 for val in range(99)] + containers = (list, tuple) #+ ((np.asarray,) if np else ()) + for fmt in 'fd': + for endi in (True, False): + for cont in containers: + conv = cont(values) + msg = 'fmt=%s, endianness=%s, container=%s' % (fmt, endi, cont.__name__) + try: + block = util.to_ieee_block(conv, fmt, endi) + parsed = util.from_ieee_block(block, fmt, endi, cont) + except Exception as e: + raise Exception(msg + '\n' + repr(e)) + + self.assertEqual(conv, parsed, msg) diff --git a/pyvisa/thirdparty/__init__.py b/pyvisa/thirdparty/__init__.py new file mode 100644 index 0000000..6a0eea1 --- /dev/null +++ b/pyvisa/thirdparty/__init__.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.thirdparty + ~~~~~~~~~~~~~~~~~ + + Third party libraries and modules bundled with PyVISA. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" diff --git a/pyvisa/thirdparty/prettytable.py b/pyvisa/thirdparty/prettytable.py new file mode 100644 index 0000000..8abb952 --- /dev/null +++ b/pyvisa/thirdparty/prettytable.py @@ -0,0 +1,1475 @@ +#!/usr/bin/env python +# +# Copyright (c) 2009-2013, Luke Maurits +# All rights reserved. +# With contributions from: +# * Chris Clark +# * Klein Stephane +# +# 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. + +__version__ = "0.7.2" + +import copy +import csv +import random +import re +import sys +import textwrap +import itertools +import unicodedata + +py3k = sys.version_info[0] >= 3 +if py3k: + unicode = str + basestring = str + itermap = map + iterzip = zip + uni_chr = chr + from html.parser import HTMLParser +else: + itermap = itertools.imap + iterzip = itertools.izip + uni_chr = unichr + from HTMLParser import HTMLParser + +if py3k and sys.version_info[1] >= 2: + from html import escape +else: + from cgi import escape + +# hrule styles +FRAME = 0 +ALL = 1 +NONE = 2 +HEADER = 3 + +# Table styles +DEFAULT = 10 +MSWORD_FRIENDLY = 11 +PLAIN_COLUMNS = 12 +RANDOM = 20 + +_re = re.compile("\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 + 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 + 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""" + + self.encoding = kwargs.get("encoding", "UTF-8") + + # Data + self._field_names = [] + self._align = {} + self._valign = {} + self._max_width = {} + self._rows = [] + if field_names: + self.field_names = field_names + else: + self._widths = [] + + # Options + self._options = "start end fields header border sortby reversesort sort_key attributes format hrules vrules".split() + self._options.extend("int_format float_format padding_width left_padding_width right_padding_width".split()) + self._options.extend("vertical_char horizontal_char junction_char header_style valign xhtml print_empty".split()) + for option in self._options: + if option in kwargs: + self._validate_option(option, kwargs[option]) + else: + kwargs[option] = 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) + + self._int_format = kwargs["int_format"] or {} + self._float_format = kwargs["float_format"] or {} + 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 + 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 MANAGMENT 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", "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"): + 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) + else: + raise Exception("Unrecognised option: %s!" % option) + + 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 %s: %s!" % (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() + 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 # + ############################## + + def _get_field_names(self): + return self._field_names + """The names of the fields + + Arguments: + + fields - list or tuple of field names""" + def _set_field_names(self, val): + val = [self._unicode(x) for x in val] + self._validate_option("field_names", val) + 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: + for field in self._field_names: + self._align[field] = "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: + for field in self._field_names: + self._valign[field] = "t" + field_names = property(_get_field_names, _set_field_names) + + def _get_align(self): + return self._align + def _set_align(self, val): + self._validate_align(val) + for field in self._field_names: + self._align[field] = val + align = property(_get_align, _set_align) + + def _get_valign(self): + return self._valign + def _set_valign(self, val): + self._validate_valign(val) + for field in self._field_names: + self._valign[field] = val + valign = property(_get_valign, _set_valign) + + def _get_max_width(self): + return self._max_width + def _set_max_width(self, val): + self._validate_option("max_width", val) + for field in self._field_names: + self._max_width[field] = val + max_width = property(_get_max_width, _set_max_width) + + def _get_fields(self): + """List or tuple of field names to include in displays + + Arguments: + + fields - list or tuple of field names to include in displays""" + return self._fields + def _set_fields(self, val): + self._validate_option("fields", val) + self._fields = val + fields = property(_get_fields, _set_fields) + + def _get_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 + + def _set_start(self, val): + self._validate_option("start", val) + self._start = val + start = property(_get_start, _set_start) + + def _get_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 + def _set_end(self, val): + self._validate_option("end", val) + self._end = val + end = property(_get_end, _set_end) + + def _get_sortby(self): + """Name of field by which to sort rows + + Arguments: + + sortby - field name to sort by""" + return self._sortby + def _set_sortby(self, val): + self._validate_option("sortby", val) + self._sortby = val + sortby = property(_get_sortby, _set_sortby) + + def _get_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 + def _set_reversesort(self, val): + self._validate_option("reversesort", val) + self._reversesort = val + reversesort = property(_get_reversesort, _set_reversesort) + + def _get_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 + def _set_sort_key(self, val): + self._validate_option("sort_key", val) + self._sort_key = val + sort_key = property(_get_sort_key, _set_sort_key) + + def _get_header(self): + """Controls printing of table header with field names + + Arguments: + + header - print a header showing field names (True or False)""" + return self._header + def _set_header(self, val): + self._validate_option("header", val) + self._header = val + header = property(_get_header, _set_header) + + def _get_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 + def _set_header_style(self, val): + self._validate_header_style(val) + self._header_style = val + header_style = property(_get_header_style, _set_header_style) + + def _get_border(self): + """Controls printing of border around table + + Arguments: + + border - print a border around the table (True or False)""" + return self._border + def _set_border(self, val): + self._validate_option("border", val) + self._border = val + border = property(_get_border, _set_border) + + def _get_hrules(self): + """Controls printing of horizontal rules after rows + + Arguments: + + hrules - horizontal rules style. Allowed values: FRAME, ALL, HEADER, NONE""" + return self._hrules + def _set_hrules(self, val): + self._validate_option("hrules", val) + self._hrules = val + hrules = property(_get_hrules, _set_hrules) + + def _get_vrules(self): + """Controls printing of vertical rules between columns + + Arguments: + + vrules - vertical rules style. Allowed values: FRAME, ALL, NONE""" + return self._vrules + def _set_vrules(self, val): + self._validate_option("vrules", val) + self._vrules = val + vrules = property(_get_vrules, _set_vrules) + + def _get_int_format(self): + """Controls formatting of integer data + Arguments: + + int_format - integer format string""" + return self._int_format + def _set_int_format(self, val): +# self._validate_option("int_format", val) + for field in self._field_names: + self._int_format[field] = val + int_format = property(_get_int_format, _set_int_format) + + def _get_float_format(self): + """Controls formatting of floating point data + Arguments: + + float_format - floating point format string""" + return self._float_format + def _set_float_format(self, val): +# self._validate_option("float_format", val) + for field in self._field_names: + self._float_format[field] = val + float_format = property(_get_float_format, _set_float_format) + + def _get_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 + def _set_padding_width(self, val): + self._validate_option("padding_width", val) + self._padding_width = val + padding_width = property(_get_padding_width, _set_padding_width) + + def _get_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 + def _set_left_padding_width(self, val): + self._validate_option("left_padding_width", val) + self._left_padding_width = val + left_padding_width = property(_get_left_padding_width, _set_left_padding_width) + + def _get_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 + def _set_right_padding_width(self, val): + self._validate_option("right_padding_width", val) + self._right_padding_width = val + right_padding_width = property(_get_right_padding_width, _set_right_padding_width) + + def _get_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 + def _set_vertical_char(self, val): + val = self._unicode(val) + self._validate_option("vertical_char", val) + self._vertical_char = val + vertical_char = property(_get_vertical_char, _set_vertical_char) + + def _get_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 + def _set_horizontal_char(self, val): + val = self._unicode(val) + self._validate_option("horizontal_char", val) + self._horizontal_char = val + horizontal_char = property(_get_horizontal_char, _set_horizontal_char) + + def _get_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 + def _set_junction_char(self, val): + val = self._unicode(val) + self._validate_option("vertical_char", val) + self._junction_char = val + junction_char = property(_get_junction_char, _set_junction_char) + + def _get_format(self): + """Controls whether or not HTML tables are formatted to match styling options + + Arguments: + + format - True or False""" + return self._format + def _set_format(self, val): + self._validate_option("format", val) + self._format = val + format = property(_get_format, _set_format) + + def _get_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 + def _set_print_empty(self, val): + self._validate_option("print_empty", val) + self._print_empty = val + print_empty = property(_get_print_empty, _set_print_empty) + + def _get_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 + def _set_attributes(self, val): + self._validate_option("attributes", val) + self._attributes = val + attributes = property(_get_attributes, _set_attributes) + + ############################## + # 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 == RANDOM: + self._set_random_style() + else: + raise Exception("Invalid pre-set style!") + + 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("~!@#$%^&*()_+|-=\{}[];':\",./;<>?") + self.horizontal_char = random.choice("~!@#$%^&*()_+|-=\{}[];':\",./;<>?") + self.junction_char = random.choice("~!@#$%^&*()_+|-=\{}[];':\",./;<>?") + + ############################## + # 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_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]) + 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.""" + + # Make a copy of only those rows in the slice range + rows = copy.deepcopy(self._rows[options["start"]:options["end"]]) + # Sort if necessary + 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] + 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: + + 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) + + # Add header or top of border + self._hrule = self._stringify_hrule(options) + 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_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) + + ############################## + # HTML STRING METHODS # + ############################## + + def get_html_string(self, **kwargs): + + """Return string representation of HTML formatted version of table in current state. + + Arguments: + + 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 = [] + open_tag.append("") + lines.append("".join(open_tag)) + + # 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
") + + 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 = [] + open_tag.append("") + lines.append("".join(open_tag)) + + # 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" % (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" % (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, 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): + + 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 + +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 + + def handle_starttag(self,tag, attrs): + self.active = tag + if tag == "th": + self.is_last_row_header = True + + def handle_endtag(self,tag): + if tag in ["th", "td"]: + stripped_content = self.last_content.strip() + self.last_row.append(stripped_content) + 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] == True: + 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(): + + x = PrettyTable(["City name", "Area", "Population", "Annual Rainfall"]) + x.sortby = "Population" + x.reversesort = True + x.int_format["Area"] = "04d" + x.float_format = "6.1f" + 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) + +if __name__ == "__main__": + main() diff --git a/pyvisa/util.py b/pyvisa/util.py new file mode 100644 index 0000000..8fcbf1f --- /dev/null +++ b/pyvisa/util.py @@ -0,0 +1,593 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.util + ~~~~~~~~~~~ + + General utility functions. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import functools +import io +import os +import platform +import sys +import subprocess +import warnings + +from .compat import check_output, string_types, OrderedDict, struct +from . import __version__, logger + + +def read_user_library_path(): + """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 + + Return `None` if configuration files or keys are not present. + + """ + try: + from ConfigParser import SafeConfigParser as ConfigParser, NoSectionError + except ImportError: + from configparser import ConfigParser, 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 (KeyError, NoSectionError): + logger.debug('KeyError or NoSectionError while reading config file') + return None + + +class LibraryPath(str): + + #: Architectural information (32, ) or (64, ) or (32, 64) + _arch = None + + def __new__(cls, path, found_by='auto'): + obj = super(LibraryPath, cls).__new__(cls, path) + obj.path = path + obj.found_by = found_by + + return obj + + @property + def arch(self): + if self._arch is None: + try: + self._arch = get_arch(self.path) + except: + self._arch = tuple() + + return self._arch + + @property + def is_32bit(self): + if not self.arch: + return 'n/a' + return 32 in self.arch + + @property + def is_64bit(self): + if not self.arch: + return 'n/a' + return 64 in self.arch + + @property + def bitness(self): + if not self.arch: + return 'n/a' + return ', '.join(str(a) for a in self.arch) + + +def warn_for_invalid_kwargs(keyw, allowed_keys): + 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): + 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): + 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 = { + 's': str, + 'b': functools.partial(int, base=2), + 'c': chr, + 'd': int, + 'o': functools.partial(int, base=8), + 'x': functools.partial(int, base=16), + 'X': functools.partial(int, base=16), + 'e': float, + 'E': float, + 'f': float, + 'F': float, + 'g': float, + 'G': float, +} + + +def from_ascii_block(ascii_data, converter='f', separator=',', container=list): + """Parse ascii data and return an iterable of numbers. + + :param ascii_data: data to be parsed. + :type ascii_data: str + :param converter: function used to convert each value. + Defaults to float + :type converter: callable + :param separator: a callable that split the str into individual elements. + If a str is given, data.split(separator) is used. + :type: separator: (str) -> collections.Iterable[T] | str + :param container: container type to use for the output data. + """ + + if isinstance(converter, string_types): + try: + converter = _converters[converter] + except KeyError: + raise ValueError('Invalid code for converter: %s not in %s' % (converter, str(tuple(_converters.keys())))) + + if isinstance(separator, string_types): + 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, converter='f', separator=','): + """Parse ascii data and return an iterable of numbers. + + :param iterable: data to be parsed. + :type iterable: collections.Iterable[T] + :param converter: function used to convert each value. + String formatting codes are also accepted. + Defaults to str. + :type converter: callable | str + :param separator: a callable that split the str into individual elements. + If a str is given, data.split(separator) is used. + :type: separator: (collections.Iterable[T]) -> str | str + """ + + if isinstance(separator, string_types): + separator = separator.join + + if isinstance(converter, string_types): + converter = '%' + converter + return separator(converter % val for val in iterable) + else: + return separator(converter(val) for val in iterable) + + +def parse_binary(bytes_data, is_big_endian=False, is_single=False): + """Parse ascii data and return an iterable of numbers. + + To be deprecated in 1.7 + + :param bytes_data: data to be parsed. + :param is_big_endian: boolean indicating the endianness. + :param is_single: boolean indicating the type (if not is double) + :return: + """ + data = bytes_data + + hash_sign_position = bytes_data.find(b"#") + if hash_sign_position == -1: + raise ValueError('Could not find valid hash position') + + if hash_sign_position > 0: + data = data[hash_sign_position:] + + data_1 = data[1:2].decode('ascii') + + if data_1.isdigit() and int(data_1) > 0: + number_of_digits = int(data_1) + # I store data and data_length in two separate variables in case + # that data is too short. FixMe: Maybe I should raise an error if + # it's too long and the trailing part is not just CR/LF. + data_length = int(data[2:2 + number_of_digits]) + data = data[2 + number_of_digits:2 + number_of_digits + data_length] + else: + data = data[2:] + if data[-1:].decode('ascii') == "\n": + data = data[:-1] + data_length = len(data) + + if is_big_endian: + endianess = ">" + else: + endianess = "<" + + try: + if is_single: + fmt = endianess + str(data_length // 4) + 'f' + else: + fmt = endianess + str(data_length // 8) + 'd' + + result = list(struct.unpack(fmt, data)) + except struct.error: + raise ValueError("Binary data itself was malformed") + + return result + + +def parse_ieee_block_header(block): + """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 + + :param block: IEEE block. + :type block: bytes + :return: (offset, data_length) + :rtype: (int, int) + """ + begin = block.find(b'#') + if begin < 0: + raise ValueError("Could not find hash sign (#) indicating the start of the block.") + + 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 = len(block) - offset - 1 + + return offset, data_length + + +def from_ieee_block(block, datatype='f', is_big_endian=False, container=list): + """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 + + :param block: IEEE block. + :type block: bytes + :param datatype: the format string for a single element. See struct module. + :param is_big_endian: boolean indicating endianess. + :param container: container type to use for the output data. + :return: items + :rtype: type(container) + """ + + offset, data_length = parse_ieee_block_header(block) + + 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, offset=0, data_length=None, datatype='f', is_big_endian=False, container=list): + """Convert a binary block into an iterable of numbers. + + :param block: binary block. + :type block: bytes + :param offset: offset at which the data block starts (default=0) + :param data_length: size in bytes of the data block (default=len(block) - offset) + :param datatype: the format string for a single element. See struct module. + :param is_big_endian: boolean indicating endianess. + :param container: container type to use for the output data. + :return: items + :rtype: type(container) + """ + + 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 '<' + + fullfmt = '%s%d%s' % (endianess, array_length, datatype) + + try: + return container(struct.unpack_from(fullfmt, block, offset)) + except struct.error: + raise ValueError("Binary data was malformed") + + +def to_ieee_block(iterable, datatype='f', is_big_endian=False): + """Convert an iterable of numbers into a block of data in the IEEE format. + + :param iterable: an iterable of numbers. + :param datatype: the format string for a single element. See struct module. + :param is_big_endian: boolean indicating endianess. + :return: IEEE block. + :rtype: bytes + """ + + 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) + + endianess = '>' if is_big_endian else '<' + fullfmt = '%s%d%s' % (endianess, array_length, datatype) + + if sys.version >= '3': + return bytes(header, 'ascii') + struct.pack(fullfmt, *iterable) + else: + return str(header) + struct.pack(fullfmt, *iterable) + + +def get_system_details(backends=True): + """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() + + 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, indent=''): + """Return a str with the system details. + """ + + l = ['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, string_types): + 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 + + l.extend(_to_list('Backends', d['backends'])) + + joiner = '\n' + indent + return indent + joiner.join(l) + '\n' + + +def get_debug_info(to_screen=True): + out = system_details_to_str(get_system_details()) + if not to_screen: + return out + print(out) + + +def pip_install(package): + try: + # noinspection PyPackageRequirements,PyUnresolvedReferences + import pip + 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): + with io.open(filename, 'rb') as fp: + dos_headers = fp.read(64) + _ = fp.read(4) + + magic, skip, offset = struct.unpack(str('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): + 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 not this_platform in ('linux2', 'linux3', 'linux', 'darwin'): + raise OSError('') + + out = check_output(["file", filename], stderr=subprocess.STDOUT) + out = out.decode('ascii') + ret = [] + if this_platform.startswith('linux'): + if '32-bit' in out: + ret.append(32) + if '64-bit' in out: + ret.append(64) + elif this_platform == 'darwin': + if '(for architecture i386)' in out: + ret.append(32) + if '(for architecture x86_64)' in out: + ret.append(64) + + return tuple(ret) diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..9717861 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,4 @@ +[check-manifest] +ignore = + .travis.yml + tox.ini diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..4df01b9 --- /dev/null +++ b/setup.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +try: + import sys + reload(sys).setdefaultencoding("UTF-8") +except: + pass + + +try: + from setuptools import setup +except ImportError: + print('Please install or upgrade setuptools or pip to continue') + sys.exit(1) + + +import codecs + + +def read(filename): + return codecs.open(filename, encoding='utf-8').read() + + +long_description = '\n\n'.join([read('README'), + read('AUTHORS'), + read('CHANGES')]) + +__doc__ = long_description + +requirements = [] +if sys.version_info < (3, 4): + requirements.append('enum34') + +if sys.version_info < (2, 7): + requirements.append('unittest2') + +setup(name='PyVISA', + description='Python VISA bindings for GPIB, RS232, and USB instruments', + version='1.8', + long_description=long_description, + author='Torsten Bronger, Gregor Thalhammer', + author_email='bronger@physik.rwth-aachen.de', + maintainer='Hernan E. Grecco', + maintainer_email='hernan.grecco@gmail.com', + url='https://github.com/hgrecco/pyvisa', + test_suite='pyvisa.testsuite.testsuite', + keywords='VISA GPIB USB serial RS232 measurement acquisition', + license='MIT License', + install_requires=requirements, + 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 :: 2.6', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3.2', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + ], + packages=['pyvisa', 'pyvisa.compat', + 'pyvisa.ctwrapper', + 'pyvisa.resources', + 'pyvisa.thirdparty', + 'pyvisa.testsuite'], + platforms="Linux, Windows,Mac", + py_modules=['visa'], + use_2to3=False, + zip_safe=False) diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..6478ef5 --- /dev/null +++ b/tox.ini @@ -0,0 +1,11 @@ +[tox] +envlist = py26,py27,py32,py33 + +[testenv] +deps= + pytest + sphinx + mock + +commands= + py.test diff --git a/visa.py b/visa.py new file mode 100644 index 0000000..120c433 --- /dev/null +++ b/visa.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.visa + ~~~~~~~~~~~ + + Module to provide an import shortcut for the most common VISA operations. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see COPYING for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +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 + +if __name__ == '__main__': + import argparse + parser = argparse.ArgumentParser(description='PyVISA command-line utilities') + subparsers = parser.add_subparsers(title='command', dest='command') + + info_parser = subparsers.add_parser('info', help='print information to diagnose PyVISA') + + console_parser = subparsers.add_parser('shell', help='start the PyVISA console') + + args = parser.parse_args() + if args.command == 'info': + from pyvisa import util + util.get_debug_info() + elif args.command == 'shell': + from pyvisa import shell + shell.main() -- cgit v1.2.3 From 4f6e88b466c46b307e73bf2498f0e912702d5c15 Mon Sep 17 00:00:00 2001 From: Ruben Undheim Date: Thu, 22 Sep 2016 19:22:55 +0200 Subject: Import pyvisa_1.8-4.debian.tar.xz [dgit import tarball pyvisa 1.8-4 pyvisa_1.8-4.debian.tar.xz] --- .git-dpm | 11 ++++ changelog | 110 ++++++++++++++++++++++++++++++++++++ compat | 1 + control | 49 ++++++++++++++++ copyright | 149 +++++++++++++++++++++++++++++++++++++++++++++++++ gbp.conf | 2 + python-pyvisa.docs | 1 + python-pyvisa.install | 3 + python3-pyvisa.docs | 1 + python3-pyvisa.install | 3 + rules | 25 +++++++++ source/format | 1 + watch | 2 + 13 files changed, 358 insertions(+) create mode 100644 .git-dpm create mode 100644 changelog create mode 100644 compat create mode 100644 control create mode 100644 copyright create mode 100644 gbp.conf create mode 100644 python-pyvisa.docs create mode 100644 python-pyvisa.install create mode 100644 python3-pyvisa.docs create mode 100644 python3-pyvisa.install create mode 100755 rules create mode 100644 source/format create mode 100644 watch diff --git a/.git-dpm b/.git-dpm new file mode 100644 index 0000000..67f3f17 --- /dev/null +++ b/.git-dpm @@ -0,0 +1,11 @@ +# see git-dpm(1) from git-dpm package +a5c3cbf9b15ec3f61547dc5ba6d1d3c427c29f70 +a5c3cbf9b15ec3f61547dc5ba6d1d3c427c29f70 +a5c3cbf9b15ec3f61547dc5ba6d1d3c427c29f70 +a5c3cbf9b15ec3f61547dc5ba6d1d3c427c29f70 +pyvisa_1.8.orig.tar.gz +9f38c897d303ea49a546b58d6b356799fbcd2e84 +423435 +debianTag="debian/%e%v" +patchedTag="patched/%e%v" +upstreamTag="upstream/%e%u" diff --git a/changelog b/changelog new file mode 100644 index 0000000..faed03f --- /dev/null +++ b/changelog @@ -0,0 +1,110 @@ +pyvisa (1.8-4) unstable; urgency=low + + * Moved python-pyvisa-py back from Depends to Recommends. (Closes: #836963) + This fixes a circular dependency issue. + + -- Ruben Undheim Thu, 22 Sep 2016 19:22:55 +0200 + +pyvisa (1.8-3) unstable; urgency=medium + + [ Ondřej Nový ] + * Fixed VCS URL (https) + + [ Ruben Undheim ] + * debian/control: + - Move libvisa0 from Depends to Suggests + - Move python-pyvisa-py from Recommends to Depends + - New Standards version 3.9.8 + + -- Ruben Undheim Sat, 27 Aug 2016 10:41:27 +0200 + +pyvisa (1.8-2) unstable; urgency=low + + * debian/control: + - Recommend pyvisa-py + - Small improvement of package description + + -- Ruben Undheim Sat, 12 Sep 2015 01:38:44 +0200 + +pyvisa (1.8-1) unstable; urgency=low + + * New upstream release + + -- Ruben Undheim Tue, 01 Sep 2015 22:26:12 +0200 + +pyvisa (1.7-1) unstable; urgency=medium + + * New upstream release + * Updated d/copyright with info about new files. + * d/control: + - transitional package pyvisa moved to Section "oldlibs" and description + changed. + + -- Ruben Undheim Fri, 29 May 2015 16:50:18 +0200 + +pyvisa (1.6.3-4) unstable; urgency=medium + + * d/control: + - Added missing install dependencies: python-pkg-resources and + python3-pkg-resources + + -- Ruben Undheim Thu, 28 May 2015 22:45:17 +0200 + +pyvisa (1.6.3-3) unstable; urgency=low + + * Uploaded to unstable + + -- Ruben Undheim Sat, 23 May 2015 11:55:57 +0200 + +pyvisa (1.6.3-2) experimental; urgency=low + + * Added python3 binary: python3-pyvisa + * Renamed pyvisa binary to python-pyvisa + * debian/copyright: + - Added copyright year and comment for Hernan E. Grecco + * debian/control: + - Added everything needed for building python3 binary as well + as python2 binary. + - Cleaned up Build-Depends list + - Section: python, Priority: optional + - python-pyvisa "replaces" and "breaks" pyvisa to provide backwards + compatibility + - pyvisa transitional dummy package added + * debian/docs --> python-pyvisa.docs and python3-pyvisa.docs + * debian/install --> python-pyvisa.install and python3-pyvisa.install + * debian/rules: + - Added --with python3 and --buildsystem=python_distutils + - More in override_dh_auto_clean to properly clean up + - override_dh_auto_build and override_dh_auto_install for building + python3 binary correctly. + + -- Ruben Undheim Mon, 16 Mar 2015 19:11:37 +0100 + +pyvisa (1.6.3-1) experimental; urgency=low + + * New upstream release (Closes: 775767) + - All patches removed + * New maintainer + * debian/control: + - Added new dependencies: dh-python, {python:Depends} + - Removed unneeded dependencies + - Standards-version to 3.9.6 + - Added X-Python-Version + * debian/copyright: + - Added new copyright holders + - Changed source URL + * debian/rules: + - Added override_dh_auto_clean to properly clean + - Install CHANGES as upstream changelog since it + is the newest + * debian/watch: Changed URL (upstream has changed) + * Added debian/gbp.conf to enable pristine-tar build + * Added debian/docs and debian/install for installing docs + + -- Ruben Undheim Thu, 12 Mar 2015 07:44:18 +0100 + +pyvisa (1.4-1) unstable; urgency=low + + * Initial release + + -- Simon Richter Tue, 29 Jan 2013 23:50:45 +0100 diff --git a/compat b/compat new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/compat @@ -0,0 +1 @@ +9 diff --git a/control b/control new file mode 100644 index 0000000..79f40fe --- /dev/null +++ b/control @@ -0,0 +1,49 @@ +Source: pyvisa +Section: python +Priority: optional +Maintainer: Debian Python Modules Team +Uploaders: Ruben Undheim +Build-Depends: debhelper (>= 9), + dh-python, + python-all, + python-setuptools, + python3-all, + python3-setuptools +Standards-Version: 3.9.8 +X-Python-Version: all +X-Python3-Version: >= 3.1 +Vcs-Browser: https://anonscm.debian.org/cgit/python-modules/packages/pyvisa.git +Vcs-Git: https://anonscm.debian.org/git/python-modules/packages/pyvisa.git +Homepage: http://pyvisa.sourceforge.net/ + +Package: pyvisa +Depends: python-pyvisa, ${misc:Depends} +Architecture: all +Priority: extra +Section: oldlibs +Description: Transitional dummy package for python-pyvisa + This is a transitional dummy package. It can safely be removed. + +Package: python-pyvisa +Architecture: all +Depends: python-pkg-resources, ${python:Depends}, ${misc:Depends} +Recommends: python-pyvisa-py +Suggests: libvisa0 +Replaces: pyvisa (<< 1.6.3-2) +Breaks: pyvisa (<< 1.6.3-2) +Description: Python bindings for Virtual Instrument Software Architecture + The VISA standard provides a common interface for communication with test + and measurement equipment. + . + This package provides Python bindings for VISA. + +Package: python3-pyvisa +Architecture: all +Depends: python3-pkg-resources, ${python3:Depends}, ${misc:Depends} +Recommends: python3-pyvisa-py +Suggests: libvisa0 +Description: Python 3 bindings for Virtual Instrument Software Architecture + The VISA standard provides a common interface for communication with test + and measurement equipment. + . + This package provides Python 3 bindings for VISA. diff --git a/copyright b/copyright new file mode 100644 index 0000000..0cae160 --- /dev/null +++ b/copyright @@ -0,0 +1,149 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: pyvisa +Source: https://github.com/hgrecco/pyvisa + +Files: * +Copyright: 2005-2014 PyVISA Authors and contributors + 2005, 2006, 2007, 2008 Torsten Bronger + 2005, 2006, 2007, 2008 Gregor Thalhammer + 2012, 2013 Florian Bauer + 2013-2015 Hernan E. Grecco +License: MIT +Comment: Hernan E. Grecco is the current upstream and his commits (and copyright + dates) can be checked at https://github.com/hgrecco/pyvisa + +Files: docs/default.css +Copyright: ? David Goodger +License: public-domain + This stylesheet has been placed in the public domain. + +Files: pyvisa/thirdparty/prettytable.py +Copyright: 2009-2013 Luke Maurits +License: BSD-3-clause + +Files: pyvisa/compat/check_output.py + pyvisa/compat/nullhandler.py + pyvisa/compat/struct.py +Copyright: 2013, 2015 PSF +License: PSF + +Files: pyvisa/compat/ordereddict.py +Copyright: 2009 Raymond Hettinger +License: MIT + +Files: docs/_themes/* +Copyright: 2010 Armin Ronacher +License: BSD-3-clause + +Files: docs/_themes/sphinx_rtd_theme/search.html + docs/_themes/sphinx_rtd_theme/layout_old.html +Copyright: 2007-2013 Sphinx team +License: BSD-3-clause + +Files: debian/* +Copyright: 2013 Simon Richter + 2015 Ruben Undheim +License: GPL-2+ + + + +License: MIT + 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. + + +License: GPL-2+ + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + . + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program. If not, see + . + On Debian systems, the complete text of the GNU General + Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". + + +License: BSD-3-clause + 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. + +License: PSF + 1. This LICENSE AGREEMENT is between the Python Software Foundation + ("PSF"), and the Individual or Organization ("Licensee") accessing and + otherwise using this software ("Python") in source or binary form and + its associated documentation. + . + 2. Subject to the terms and conditions of this License Agreement, PSF + hereby grants Licensee a nonexclusive, royalty-free, world-wide + license to reproduce, analyze, test, perform and/or display publicly, + prepare derivative works, distribute, and otherwise use Python + alone or in any derivative version, provided, however, that PSF's + License Agreement and PSF's notice of copyright, i.e., "Copyright (c) + 2001, 2002, 2003, 2004, 2005, 2006 Python Software Foundation; All Rights + Reserved" are retained in Python alone or in any derivative version + prepared by Licensee. + . + 3. In the event Licensee prepares a derivative work that is based on + or incorporates Python or any part thereof, and wants to make + the derivative work available to others as provided herein, then + Licensee hereby agrees to include in any such work a brief summary of + the changes made to Python. + . + 4. PSF is making Python available to Licensee on an "AS IS" + basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR + IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND + DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS + FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT + INFRINGE ANY THIRD PARTY RIGHTS. + . + 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON + FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS + A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, + OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + . + 6. This License Agreement will automatically terminate upon a material + breach of its terms and conditions. + . + 7. Nothing in this License Agreement shall be deemed to create any + relationship of agency, partnership, or joint venture between PSF and + Licensee. This License Agreement does not grant permission to use PSF + trademarks or trade name in a trademark sense to endorse or promote + products or services of Licensee, or any third party. + . + 8. By copying, installing or otherwise using Python, Licensee + agrees to be bound by the terms and conditions of this License + Agreement. diff --git a/gbp.conf b/gbp.conf new file mode 100644 index 0000000..cec628c --- /dev/null +++ b/gbp.conf @@ -0,0 +1,2 @@ +[DEFAULT] +pristine-tar = True diff --git a/python-pyvisa.docs b/python-pyvisa.docs new file mode 100644 index 0000000..e845566 --- /dev/null +++ b/python-pyvisa.docs @@ -0,0 +1 @@ +README diff --git a/python-pyvisa.install b/python-pyvisa.install new file mode 100644 index 0000000..18ec81e --- /dev/null +++ b/python-pyvisa.install @@ -0,0 +1,3 @@ +usr/lib/python2*/ +docs/*.rst usr/share/doc/python-pyvisa/manual/rst +docs/api/*.rst usr/share/doc/python-pyvisa/manual/rst/api diff --git a/python3-pyvisa.docs b/python3-pyvisa.docs new file mode 100644 index 0000000..e845566 --- /dev/null +++ b/python3-pyvisa.docs @@ -0,0 +1 @@ +README diff --git a/python3-pyvisa.install b/python3-pyvisa.install new file mode 100644 index 0000000..e292b81 --- /dev/null +++ b/python3-pyvisa.install @@ -0,0 +1,3 @@ +usr/lib/python3*/ +docs/*.rst usr/share/doc/python3-pyvisa/manual/rst +docs/api/*.rst usr/share/doc/python3-pyvisa/manual/rst/api diff --git a/rules b/rules new file mode 100755 index 0000000..f2157ab --- /dev/null +++ b/rules @@ -0,0 +1,25 @@ +#!/usr/bin/make -f + +%: + dh $@ --with python2,python3 --buildsystem=python_distutils + +override_dh_auto_clean: + $(RM) -r PyVISA.egg-info + $(RM) -r build + dh_auto_clean + +override_dh_auto_build: + dh_auto_build + set -ex; for python in $(shell py3versions -r); do \ + $$python setup.py build; \ + done + +override_dh_auto_install: + dh_auto_install + set -ex; for python in $(shell py3versions -r); do \ + $$python setup.py install --install-layout=deb \ + --root $(CURDIR)/debian/tmp; \ + done; + +override_dh_installchangelogs: + dh_installchangelogs -k CHANGES diff --git a/source/format b/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/watch b/watch new file mode 100644 index 0000000..c0f5f5a --- /dev/null +++ b/watch @@ -0,0 +1,2 @@ +version=3 +https://github.com/hgrecco/pyvisa/releases /hgrecco/pyvisa/archive/(\d\S+)\.tar\.(?:bz2|gz|xz) -- cgit v1.2.3 From f0b2a6245b8f13e9a098fee175ef324d16af910f Mon Sep 17 00:00:00 2001 From: Ruben Undheim Date: Sun, 5 Aug 2018 19:28:21 +0000 Subject: Fix build Gbp-Pq: Name 0001-fix-build.patch --- setup.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index a3d05a8..43c0732 100644 --- a/setup.py +++ b/setup.py @@ -16,13 +16,14 @@ except ImportError: def read(filename): - with open(filename, 'r') as f: + with open(filename, 'rb') as f: return f.read() +a2 = read('AUTHORS').decode('utf-8') +a3 = read('CHANGES').decode('utf-8') +a1 = read('README').decode('utf-8') -long_description = '\n\n'.join([read('README'), - read('AUTHORS'), - read('CHANGES')]) +long_description = '\n\n'.join([a1,a2,a3]) __doc__ = long_description -- cgit v1.2.3 From 1605094d64eede7fc798e9621a0f9c6591b53548 Mon Sep 17 00:00:00 2001 From: Ruben Undheim Date: Sun, 19 Aug 2018 22:22:03 +0200 Subject: Import pyvisa_1.9.1.orig.tar.gz [dgit import orig pyvisa_1.9.1.orig.tar.gz] --- .gitignore | 15 + .travis.yml | 28 + AUTHORS | 25 + CHANGES | 349 ++ ChangeLog | 995 +++++ LICENSE | 21 + MANIFEST.in | 7 + README | 80 + docs/LICENSE | 23 + docs/Makefile | 153 + docs/_static/logo-full.jpg | Bin 0 -> 10898 bytes docs/_templates/sidebarintro.html | 20 + docs/_templates/sidebarlogo.html | 23 + docs/_themes/.gitignore | 3 + docs/_themes/LICENSE | 37 + docs/_themes/README | 31 + docs/_themes/flask/layout.html | 30 + docs/_themes/flask/relations.html | 20 + docs/_themes/flask/static/flasky.css_t | 395 ++ docs/_themes/flask/static/small_flask.css | 70 + docs/_themes/flask/theme.conf | 10 + docs/_themes/flask_theme_support.py | 86 + docs/_themes/sphinx_rtd_theme/__init__.py | 17 + docs/_themes/sphinx_rtd_theme/breadcrumbs.html | 19 + docs/_themes/sphinx_rtd_theme/footer.html | 32 + docs/_themes/sphinx_rtd_theme/layout.html | 161 + docs/_themes/sphinx_rtd_theme/layout_old.html | 205 + docs/_themes/sphinx_rtd_theme/search.html | 50 + docs/_themes/sphinx_rtd_theme/searchbox.html | 7 + .../sphinx_rtd_theme/static/css/badge_only.css | 224 + docs/_themes/sphinx_rtd_theme/static/css/theme.css | 4725 ++++++++++++++++++++ .../sphinx_rtd_theme/static/fonts/FontAwesome.otf | Bin 0 -> 62856 bytes .../static/fonts/fontawesome-webfont.eot | Bin 0 -> 38205 bytes .../static/fonts/fontawesome-webfont.svg | 414 ++ .../static/fonts/fontawesome-webfont.ttf | Bin 0 -> 80652 bytes .../static/fonts/fontawesome-webfont.woff | Bin 0 -> 44432 bytes docs/_themes/sphinx_rtd_theme/static/js/theme.js | 47 + docs/_themes/sphinx_rtd_theme/theme.conf | 9 + docs/_themes/sphinx_rtd_theme/versions.html | 37 + docs/api/constants.rst | 45 + docs/api/index.rst | 14 + docs/api/resourcemanager.rst | 9 + docs/api/resources.rst | 135 + docs/api/visalibrarybase.rst | 9 + docs/architecture.rst | 120 + docs/backends.rst | 196 + docs/conf.py | 297 ++ docs/configuring.rst | 77 + docs/contributing.rst | 76 + docs/default.css | 255 ++ docs/example.rst | 72 + docs/faq.rst | 177 + docs/getting.rst | 84 + docs/getting_nivisa.rst | 90 + docs/index.rst | 90 + docs/make.bat | 190 + docs/migrating.rst | 294 ++ docs/names.rst | 157 + docs/resources.rst | 166 + docs/rvalues.rst | 205 + docs/shell.rst | 213 + docs/tutorial.rst | 96 + examples/itc4.py | 43 + examples/keithley2000.py | 51 + pyvisa/__init__.py | 51 + pyvisa/attributes.py | 3292 ++++++++++++++ pyvisa/compat/__init__.py | 144 + pyvisa/compat/nullhandler.py | 35 + pyvisa/compat/ordereddict.py | 127 + pyvisa/compat/struct.py | 43 + pyvisa/constants.py | 1060 +++++ pyvisa/ctwrapper/__init__.py | 19 + pyvisa/ctwrapper/cthelper.py | 85 + pyvisa/ctwrapper/functions.py | 1901 ++++++++ pyvisa/ctwrapper/highlevel.py | 256 ++ pyvisa/ctwrapper/types.py | 157 + pyvisa/errors.py | 535 +++ pyvisa/highlevel.py | 1732 +++++++ pyvisa/resources/__init__.py | 39 + pyvisa/resources/firewire.py | 29 + pyvisa/resources/gpib.py | 148 + pyvisa/resources/messagebased.py | 715 +++ pyvisa/resources/pxi.py | 42 + pyvisa/resources/registerbased.py | 72 + pyvisa/resources/resource.py | 405 ++ pyvisa/resources/serial.py | 34 + pyvisa/resources/tcpip.py | 41 + pyvisa/resources/usb.py | 68 + pyvisa/resources/vxi.py | 52 + pyvisa/rname.py | 575 +++ pyvisa/shell.py | 428 ++ pyvisa/testsuite/__init__.py | 105 + pyvisa/testsuite/test_errors.py | 37 + pyvisa/testsuite/test_rname.py | 257 ++ pyvisa/testsuite/test_util.py | 114 + pyvisa/thirdparty/__init__.py | 12 + pyvisa/thirdparty/prettytable.py | 1475 ++++++ pyvisa/util.py | 739 +++ setup.cfg | 4 + setup.py | 71 + tox.ini | 11 + visa.py | 55 + 102 files changed, 26494 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 AUTHORS create mode 100644 CHANGES create mode 100644 ChangeLog create mode 100644 LICENSE create mode 100644 MANIFEST.in create mode 100644 README create mode 100644 docs/LICENSE create mode 100644 docs/Makefile create mode 100644 docs/_static/logo-full.jpg create mode 100644 docs/_templates/sidebarintro.html create mode 100644 docs/_templates/sidebarlogo.html create mode 100644 docs/_themes/.gitignore create mode 100644 docs/_themes/LICENSE create mode 100644 docs/_themes/README create mode 100644 docs/_themes/flask/layout.html create mode 100644 docs/_themes/flask/relations.html create mode 100644 docs/_themes/flask/static/flasky.css_t create mode 100644 docs/_themes/flask/static/small_flask.css create mode 100644 docs/_themes/flask/theme.conf create mode 100644 docs/_themes/flask_theme_support.py create mode 100644 docs/_themes/sphinx_rtd_theme/__init__.py create mode 100644 docs/_themes/sphinx_rtd_theme/breadcrumbs.html create mode 100644 docs/_themes/sphinx_rtd_theme/footer.html create mode 100644 docs/_themes/sphinx_rtd_theme/layout.html create mode 100644 docs/_themes/sphinx_rtd_theme/layout_old.html create mode 100644 docs/_themes/sphinx_rtd_theme/search.html create mode 100644 docs/_themes/sphinx_rtd_theme/searchbox.html create mode 100644 docs/_themes/sphinx_rtd_theme/static/css/badge_only.css create mode 100644 docs/_themes/sphinx_rtd_theme/static/css/theme.css create mode 100644 docs/_themes/sphinx_rtd_theme/static/fonts/FontAwesome.otf create mode 100644 docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.eot create mode 100644 docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg create mode 100644 docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.ttf create mode 100644 docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.woff create mode 100644 docs/_themes/sphinx_rtd_theme/static/js/theme.js create mode 100644 docs/_themes/sphinx_rtd_theme/theme.conf create mode 100644 docs/_themes/sphinx_rtd_theme/versions.html create mode 100644 docs/api/constants.rst create mode 100644 docs/api/index.rst create mode 100644 docs/api/resourcemanager.rst create mode 100644 docs/api/resources.rst create mode 100644 docs/api/visalibrarybase.rst create mode 100644 docs/architecture.rst create mode 100644 docs/backends.rst create mode 100644 docs/conf.py create mode 100644 docs/configuring.rst create mode 100644 docs/contributing.rst create mode 100644 docs/default.css create mode 100644 docs/example.rst create mode 100644 docs/faq.rst create mode 100644 docs/getting.rst create mode 100644 docs/getting_nivisa.rst create mode 100644 docs/index.rst create mode 100644 docs/make.bat create mode 100644 docs/migrating.rst create mode 100644 docs/names.rst create mode 100644 docs/resources.rst create mode 100644 docs/rvalues.rst create mode 100644 docs/shell.rst create mode 100644 docs/tutorial.rst create mode 100644 examples/itc4.py create mode 100644 examples/keithley2000.py create mode 100644 pyvisa/__init__.py create mode 100644 pyvisa/attributes.py create mode 100644 pyvisa/compat/__init__.py create mode 100644 pyvisa/compat/nullhandler.py create mode 100644 pyvisa/compat/ordereddict.py create mode 100644 pyvisa/compat/struct.py create mode 100644 pyvisa/constants.py create mode 100644 pyvisa/ctwrapper/__init__.py create mode 100644 pyvisa/ctwrapper/cthelper.py create mode 100644 pyvisa/ctwrapper/functions.py create mode 100644 pyvisa/ctwrapper/highlevel.py create mode 100644 pyvisa/ctwrapper/types.py create mode 100644 pyvisa/errors.py create mode 100644 pyvisa/highlevel.py create mode 100644 pyvisa/resources/__init__.py create mode 100644 pyvisa/resources/firewire.py create mode 100644 pyvisa/resources/gpib.py create mode 100644 pyvisa/resources/messagebased.py create mode 100644 pyvisa/resources/pxi.py create mode 100644 pyvisa/resources/registerbased.py create mode 100644 pyvisa/resources/resource.py create mode 100644 pyvisa/resources/serial.py create mode 100644 pyvisa/resources/tcpip.py create mode 100644 pyvisa/resources/usb.py create mode 100644 pyvisa/resources/vxi.py create mode 100644 pyvisa/rname.py create mode 100644 pyvisa/shell.py create mode 100644 pyvisa/testsuite/__init__.py create mode 100644 pyvisa/testsuite/test_errors.py create mode 100644 pyvisa/testsuite/test_rname.py create mode 100644 pyvisa/testsuite/test_util.py create mode 100644 pyvisa/thirdparty/__init__.py create mode 100644 pyvisa/thirdparty/prettytable.py create mode 100644 pyvisa/util.py create mode 100644 setup.cfg create mode 100644 setup.py create mode 100644 tox.ini create mode 100644 visa.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ac02c9e --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*~ +__pycache__ +*egg-info* +*.pyc +.DS_Store +docs/_build/ +.idea +build/ +dist/ +MANIFEST +.tox +.coveragerc +# WebDAV file system cache files +.DAV/ +_test/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..291df6f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,28 @@ +language: python + +branches: + only: + # This is where pull requests from "bors r+" are built. + - staging + # This is where pull requests from "bors try" are built. + - trying + # Build master too + - master + +python: + - "2.7" + - "3.4" + - "3.5" + - "3.6" + +install: + - if [ $TRAVIS_PYTHON_VERSION == '2.7' ] || [ $TRAVIS_PYTHON_VERSION == '3.6' ]; then pip install numpy; fi + - pip install coverage coveralls + +script: + - coverage run -p --source=pyvisa --omit="*test*","*compat*" setup.py test + - coverage combine + - coverage report -m + +after_script: + - coveralls --verbose diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..0c66f47 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,25 @@ +PyVISA 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 +* Martin Ritter +* Matthew94 +* Matthieu Dartiailh +* mordoror +* Tobias Müller +* Yves Delley + +If you think your name should be here, please let me know. diff --git a/CHANGES b/CHANGES new file mode 100644 index 0000000..b2409e0 --- /dev/null +++ b/CHANGES @@ -0,0 +1,349 @@ +PyVISA Changelog +================ + +1.10 (unreleased) +----------------- + +No changes yet + + +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. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..fce5efa --- /dev/null +++ b/ChangeLog @@ -0,0 +1,995 @@ +2008-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. + + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3a87755 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2005-2014 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. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..dc2ef48 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,7 @@ +include README AUTHORS CHANGES LICENSE ChangeLog +recursive-include pyvisa * +recursive-include docs * +recursive-include examples * +prune docs/_build +prune docs/_themes/.git +global-exclude *.pyc *~ .DS_Store *__pycache__* *.pyo diff --git a/README b/README new file mode 100644 index 0000000..72febd6 --- /dev/null +++ b/README @@ -0,0 +1,80 @@ +PyVISA +====== + +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 2.7 and 3.4+) +- VISA (tested with NI-VISA 17.5, Win7, from www.ni.com/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 diff --git a/docs/LICENSE b/docs/LICENSE new file mode 100644 index 0000000..271623f --- /dev/null +++ b/docs/LICENSE @@ -0,0 +1,23 @@ +The MIT License + +Copyright (c) 2005, 2006, 2007, 2008 + Torsten Bronger , + Gregor Thalhammer . + +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. diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..866ca77 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,153 @@ +# 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) . +# 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." diff --git a/docs/_static/logo-full.jpg b/docs/_static/logo-full.jpg new file mode 100644 index 0000000..763a12a Binary files /dev/null and b/docs/_static/logo-full.jpg differ diff --git a/docs/_templates/sidebarintro.html b/docs/_templates/sidebarintro.html new file mode 100644 index 0000000..7ccc188 --- /dev/null +++ b/docs/_templates/sidebarintro.html @@ -0,0 +1,20 @@ +

About PyVISA

+Python wrapper for the Virtual Instrument Software Architechture library. +You are currently looking at the documentation of version {{ version }}. +

Other Formats

+

+ You can download the documentation in other formats as well: +

+ +

Useful Links

+ + + diff --git a/docs/_templates/sidebarlogo.html b/docs/_templates/sidebarlogo.html new file mode 100644 index 0000000..e42afdf --- /dev/null +++ b/docs/_templates/sidebarlogo.html @@ -0,0 +1,23 @@ +

+ Logo +

+ +

About PyVISA

+Python wrapper for the Virtual Instrument Software Architechture library. +You are currently looking at the documentation of version {{ version }}. +

Other Formats

+

+ You can download the documentation in other formats as well: +

+ +

Useful Links

+ + diff --git a/docs/_themes/.gitignore b/docs/_themes/.gitignore new file mode 100644 index 0000000..66b6e4c --- /dev/null +++ b/docs/_themes/.gitignore @@ -0,0 +1,3 @@ +*.pyc +*.pyo +.DS_Store diff --git a/docs/_themes/LICENSE b/docs/_themes/LICENSE new file mode 100644 index 0000000..8daab7e --- /dev/null +++ b/docs/_themes/LICENSE @@ -0,0 +1,37 @@ +Copyright (c) 2010 by Armin Ronacher. + +Some rights reserved. + +Redistribution and use in source and binary forms of the theme, 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 names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +We kindly ask you to only use these themes in an unmodified manner just +for Flask and Flask-related products, not for unrelated projects. If you +like the visual style and want to use it for your own projects, please +consider making some larger changes to the themes (such as changing +font faces, sizes, colors or margins). + +THIS THEME 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 THEME, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/docs/_themes/README b/docs/_themes/README new file mode 100644 index 0000000..b3292bd --- /dev/null +++ b/docs/_themes/README @@ -0,0 +1,31 @@ +Flask Sphinx Styles +=================== + +This repository contains sphinx styles for Flask and Flask related +projects. To use this style in your Sphinx documentation, follow +this guide: + +1. put this folder as _themes into your docs folder. Alternatively + you can also use git submodules to check out the contents there. +2. add this to your conf.py: + + sys.path.append(os.path.abspath('_themes')) + html_theme_path = ['_themes'] + html_theme = 'flask' + +The following themes exist: + +- 'flask' - the standard flask documentation theme for large + projects +- 'flask_small' - small one-page theme. Intended to be used by + very small addon libraries for flask. + +The following options exist for the flask_small theme: + + [options] + index_logo = '' filename of a picture in _static + to be used as replacement for the + h1 in the index.rst file. + index_logo_height = 120px height of the index logo + github_fork = '' repository name on github for the + "fork me" badge diff --git a/docs/_themes/flask/layout.html b/docs/_themes/flask/layout.html new file mode 100644 index 0000000..4c79a9a --- /dev/null +++ b/docs/_themes/flask/layout.html @@ -0,0 +1,30 @@ +{%- extends "basic/layout.html" %} +{%- block extrahead %} + {{ super() }} + {% if theme_touch_icon %} + + {% endif %} + +{% endblock %} +{%- block relbar2 %} + {% if theme_github_fork %} + Fork me on GitHub + {% endif %} +{% endblock %} +{% block header %} + {{ super() }} + {% if pagename == 'index' %} +
+ {% endif %} +{% endblock %} +{%- block footer %} + + {% if pagename == 'index' %} +
+ {% endif %} +{%- endblock %} diff --git a/docs/_themes/flask/relations.html b/docs/_themes/flask/relations.html new file mode 100644 index 0000000..ed433fa --- /dev/null +++ b/docs/_themes/flask/relations.html @@ -0,0 +1,20 @@ + +

Related Topics

+ +{%- endfor %} +{%- if prev %} +

+ Previous
+ {{ prev.title }} +

+{%- endif %} +{%- if next %} +

+ Next
+ {{ next.title }} +

+{%- endif %} diff --git a/docs/_themes/flask/static/flasky.css_t b/docs/_themes/flask/static/flasky.css_t new file mode 100644 index 0000000..b5ca39b --- /dev/null +++ b/docs/_themes/flask/static/flasky.css_t @@ -0,0 +1,395 @@ +/* + * flasky.css_t + * ~~~~~~~~~~~~ + * + * :copyright: Copyright 2010 by Armin Ronacher. + * :license: Flask Design License, see LICENSE for details. + */ + +{% set page_width = '940px' %} +{% set sidebar_width = '220px' %} + +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: 'Georgia', serif; + font-size: 17px; + background-color: white; + color: #000; + margin: 0; + padding: 0; +} + +div.document { + width: {{ page_width }}; + margin: 30px auto 0 auto; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 {{ sidebar_width }}; +} + +div.sphinxsidebar { + width: {{ sidebar_width }}; +} + +hr { + border: 1px solid #B1B4B6; +} + +div.body { + background-color: #ffffff; + color: #3E4349; + padding: 0 30px 0 30px; +} + +img.floatingflask { + padding: 0 0 10px 10px; + float: right; +} + +div.footer { + width: {{ page_width }}; + margin: 20px auto 30px auto; + font-size: 14px; + color: #888; + text-align: right; +} + +div.footer a { + color: #888; +} + +div.related { + display: none; +} + +div.sphinxsidebar a { + color: #444; + text-decoration: none; + border-bottom: 1px dotted #999; +} + +div.sphinxsidebar a:hover { + border-bottom: 1px solid #999; +} + +div.sphinxsidebar { + font-size: 14px; + line-height: 1.5; +} + +div.sphinxsidebarwrapper { + padding: 18px 10px; +} + +div.sphinxsidebarwrapper p.logo { + padding: 0 0 20px 0; + margin: 0; + text-align: center; +} + +div.sphinxsidebar h3, +div.sphinxsidebar h4 { + font-family: 'Garamond', 'Georgia', serif; + color: #444; + font-size: 24px; + font-weight: normal; + margin: 0 0 5px 0; + padding: 0; +} + +div.sphinxsidebar h4 { + font-size: 20px; +} + +div.sphinxsidebar h3 a { + color: #444; +} + +div.sphinxsidebar p.logo a, +div.sphinxsidebar h3 a, +div.sphinxsidebar p.logo a:hover, +div.sphinxsidebar h3 a:hover { + border: none; +} + +div.sphinxsidebar p { + color: #555; + margin: 10px 0; +} + +div.sphinxsidebar ul { + margin: 10px 0; + padding: 0; + color: #000; +} + +div.sphinxsidebar input { + border: 1px solid #ccc; + font-family: 'Georgia', serif; + font-size: 1em; +} + +/* -- body styles ----------------------------------------------------------- */ + +a { + color: #004B6B; + text-decoration: underline; +} + +a:hover { + color: #6D4100; + text-decoration: underline; +} + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: 'Garamond', 'Georgia', serif; + font-weight: normal; + margin: 30px 0px 10px 0px; + padding: 0; +} + +{% if theme_index_logo %} +div.indexwrapper h1 { + text-indent: -999999px; + background: url({{ theme_index_logo }}) no-repeat center center; + height: {{ theme_index_logo_height }}; +} +{% endif %} + +div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } +div.body h2 { font-size: 180%; } +div.body h3 { font-size: 150%; } +div.body h4 { font-size: 130%; } +div.body h5 { font-size: 100%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #ddd; + padding: 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + color: #444; + background: #eaeaea; +} + +div.body p, div.body dd, div.body li { + line-height: 1.4em; +} + +div.admonition { + background: #fafafa; + margin: 20px -30px; + padding: 10px 30px; + border-top: 1px solid #ccc; + border-bottom: 1px solid #ccc; +} + +div.admonition tt.xref, div.admonition a tt { + border-bottom: 1px solid #fafafa; +} + +dd div.admonition { + margin-left: -60px; + padding-left: 60px; +} + +div.admonition p.admonition-title { + font-family: 'Garamond', 'Georgia', serif; + font-weight: normal; + font-size: 24px; + margin: 0 0 10px 0; + padding: 0; + line-height: 1; +} + +div.admonition p.last { + margin-bottom: 0; +} + +div.highlight { + background-color: white; +} + +dt:target, .highlight { + background: #FAF3E8; +} + +div.note { + background-color: #eee; + border: 1px solid #ccc; +} + +div.seealso { + background-color: #ffc; + border: 1px solid #ff6; +} + +div.topic { + background-color: #eee; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre, tt { + font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; + font-size: 0.9em; +} + +img.screenshot { +} + +tt.descname, tt.descclassname { + font-size: 0.95em; +} + +tt.descname { + padding-right: 0.08em; +} + +img.screenshot { + -moz-box-shadow: 2px 2px 4px #eee; + -webkit-box-shadow: 2px 2px 4px #eee; + box-shadow: 2px 2px 4px #eee; +} + +table.docutils { + border: 1px solid #888; + -moz-box-shadow: 2px 2px 4px #eee; + -webkit-box-shadow: 2px 2px 4px #eee; + box-shadow: 2px 2px 4px #eee; +} + +table.docutils td, table.docutils th { + border: 1px solid #888; + padding: 0.25em 0.7em; +} + +table.field-list, table.footnote { + border: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + +table.footnote { + margin: 15px 0; + width: 100%; + border: 1px solid #eee; + background: #fdfdfd; + font-size: 0.9em; +} + +table.footnote + table.footnote { + margin-top: -15px; + border-top: none; +} + +table.field-list th { + padding: 0 0.8em 0 0; +} + +table.field-list td { + padding: 0; +} + +table.footnote td.label { + width: 0px; + padding: 0.3em 0 0.3em 0.5em; +} + +table.footnote td { + padding: 0.3em 0.5em; +} + +dl { + margin: 0; + padding: 0; +} + +dl dd { + margin-left: 30px; +} + +blockquote { + margin: 0 0 0 30px; + padding: 0; +} + +ul, ol { + margin: 10px 0 10px 30px; + padding: 0; +} + +pre { + background: #eee; + padding: 7px 30px; + margin: 15px -30px; + line-height: 1.3em; +} + +dl pre, blockquote pre, li pre { + margin-left: -60px; + padding-left: 60px; +} + +dl dl pre { + margin-left: -90px; + padding-left: 90px; +} + +tt { + background-color: #ecf0f3; + color: #222; + /* padding: 1px 2px; */ +} + +tt.xref, a tt { + background-color: #FBFBFB; + border-bottom: 1px solid white; +} + +a.reference { + text-decoration: none; + border-bottom: 1px dotted #004B6B; +} + +a.reference:hover { + border-bottom: 1px solid #6D4100; +} + +a.footnote-reference { + text-decoration: none; + font-size: 0.7em; + vertical-align: top; + border-bottom: 1px dotted #004B6B; +} + +a.footnote-reference:hover { + border-bottom: 1px solid #6D4100; +} + +a:hover tt { + background: #EEE; +} diff --git a/docs/_themes/flask/static/small_flask.css b/docs/_themes/flask/static/small_flask.css new file mode 100644 index 0000000..1c6df30 --- /dev/null +++ b/docs/_themes/flask/static/small_flask.css @@ -0,0 +1,70 @@ +/* + * small_flask.css_t + * ~~~~~~~~~~~~~~~~~ + * + * :copyright: Copyright 2010 by Armin Ronacher. + * :license: Flask Design License, see LICENSE for details. + */ + +body { + margin: 0; + padding: 20px 30px; +} + +div.documentwrapper { + float: none; + background: white; +} + +div.sphinxsidebar { + display: block; + float: none; + width: 102.5%; + margin: 50px -30px -20px -30px; + padding: 10px 20px; + background: #333; + color: white; +} + +div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, +div.sphinxsidebar h3 a { + color: white; +} + +div.sphinxsidebar a { + color: #aaa; +} + +div.sphinxsidebar p.logo { + display: none; +} + +div.document { + width: 100%; + margin: 0; +} + +div.related { + display: block; + margin: 0; + padding: 10px 0 20px 0; +} + +div.related ul, +div.related ul li { + margin: 0; + padding: 0; +} + +div.footer { + display: none; +} + +div.bodywrapper { + margin: 0; +} + +div.body { + min-height: 0; + padding: 0; +} diff --git a/docs/_themes/flask/theme.conf b/docs/_themes/flask/theme.conf new file mode 100644 index 0000000..4313e2a --- /dev/null +++ b/docs/_themes/flask/theme.conf @@ -0,0 +1,10 @@ +[theme] +inherit = basic +stylesheet = flasky.css +pygments_style = flask_theme_support.FlaskyStyle + +[options] +index_logo = '' +index_logo_height = 120px +touch_icon = +github_fork = hgrecco/pyvisa diff --git a/docs/_themes/flask_theme_support.py b/docs/_themes/flask_theme_support.py new file mode 100644 index 0000000..33f4744 --- /dev/null +++ b/docs/_themes/flask_theme_support.py @@ -0,0 +1,86 @@ +# flasky extensions. flasky pygments style based on tango style +from pygments.style import Style +from pygments.token import Keyword, Name, Comment, String, Error, \ + Number, Operator, Generic, Whitespace, Punctuation, Other, Literal + + +class FlaskyStyle(Style): + background_color = "#f8f8f8" + default_style = "" + + styles = { + # No corresponding class for the following: + #Text: "", # class: '' + Whitespace: "underline #f8f8f8", # class: 'w' + Error: "#a40000 border:#ef2929", # class: 'err' + Other: "#000000", # class 'x' + + Comment: "italic #8f5902", # class: 'c' + Comment.Preproc: "noitalic", # class: 'cp' + + Keyword: "bold #004461", # class: 'k' + Keyword.Constant: "bold #004461", # class: 'kc' + Keyword.Declaration: "bold #004461", # class: 'kd' + Keyword.Namespace: "bold #004461", # class: 'kn' + Keyword.Pseudo: "bold #004461", # class: 'kp' + Keyword.Reserved: "bold #004461", # class: 'kr' + Keyword.Type: "bold #004461", # class: 'kt' + + Operator: "#582800", # class: 'o' + Operator.Word: "bold #004461", # class: 'ow' - like keywords + + Punctuation: "bold #000000", # class: 'p' + + # because special names such as Name.Class, Name.Function, etc. + # are not recognized as such later in the parsing, we choose them + # to look the same as ordinary variables. + Name: "#000000", # class: 'n' + Name.Attribute: "#c4a000", # class: 'na' - to be revised + Name.Builtin: "#004461", # class: 'nb' + Name.Builtin.Pseudo: "#3465a4", # class: 'bp' + Name.Class: "#000000", # class: 'nc' - to be revised + Name.Constant: "#000000", # class: 'no' - to be revised + Name.Decorator: "#888", # class: 'nd' - to be revised + Name.Entity: "#ce5c00", # class: 'ni' + Name.Exception: "bold #cc0000", # class: 'ne' + Name.Function: "#000000", # class: 'nf' + Name.Property: "#000000", # class: 'py' + Name.Label: "#f57900", # class: 'nl' + Name.Namespace: "#000000", # class: 'nn' - to be revised + Name.Other: "#000000", # class: 'nx' + Name.Tag: "bold #004461", # class: 'nt' - like a keyword + Name.Variable: "#000000", # class: 'nv' - to be revised + Name.Variable.Class: "#000000", # class: 'vc' - to be revised + Name.Variable.Global: "#000000", # class: 'vg' - to be revised + Name.Variable.Instance: "#000000", # class: 'vi' - to be revised + + Number: "#990000", # class: 'm' + + Literal: "#000000", # class: 'l' + Literal.Date: "#000000", # class: 'ld' + + String: "#4e9a06", # class: 's' + String.Backtick: "#4e9a06", # class: 'sb' + String.Char: "#4e9a06", # class: 'sc' + String.Doc: "italic #8f5902", # class: 'sd' - like a comment + String.Double: "#4e9a06", # class: 's2' + String.Escape: "#4e9a06", # class: 'se' + String.Heredoc: "#4e9a06", # class: 'sh' + String.Interpol: "#4e9a06", # class: 'si' + String.Other: "#4e9a06", # class: 'sx' + String.Regex: "#4e9a06", # class: 'sr' + String.Single: "#4e9a06", # class: 's1' + String.Symbol: "#4e9a06", # class: 'ss' + + Generic: "#000000", # class: 'g' + Generic.Deleted: "#a40000", # class: 'gd' + Generic.Emph: "italic #000000", # class: 'ge' + Generic.Error: "#ef2929", # class: 'gr' + Generic.Heading: "bold #000080", # class: 'gh' + Generic.Inserted: "#00A000", # class: 'gi' + Generic.Output: "#888", # class: 'go' + Generic.Prompt: "#745334", # class: 'gp' + Generic.Strong: "bold #000000", # class: 'gs' + Generic.Subheading: "bold #800080", # class: 'gu' + Generic.Traceback: "bold #a40000", # class: 'gt' + } diff --git a/docs/_themes/sphinx_rtd_theme/__init__.py b/docs/_themes/sphinx_rtd_theme/__init__.py new file mode 100644 index 0000000..1440863 --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/__init__.py @@ -0,0 +1,17 @@ +"""Sphinx ReadTheDocs theme. + +From https://github.com/ryan-roemer/sphinx-bootstrap-theme. + +""" +import os + +VERSION = (0, 1, 5) + +__version__ = ".".join(str(v) for v in VERSION) +__version_full__ = __version__ + + +def get_html_theme_path(): + """Return list of HTML theme paths.""" + cur_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) + return cur_dir diff --git a/docs/_themes/sphinx_rtd_theme/breadcrumbs.html b/docs/_themes/sphinx_rtd_theme/breadcrumbs.html new file mode 100644 index 0000000..d9b2937 --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/breadcrumbs.html @@ -0,0 +1,19 @@ +
+ +
+
diff --git a/docs/_themes/sphinx_rtd_theme/footer.html b/docs/_themes/sphinx_rtd_theme/footer.html new file mode 100644 index 0000000..21a6b55 --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/footer.html @@ -0,0 +1,32 @@ +
+ {% if next or prev %} + + {% endif %} + +
+ +
+

+ {%- if show_copyright %} + {%- if hasdoc('copyright') %} + {% trans path=pathto('copyright'), copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %} + {%- else %} + {% trans copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %} + {%- endif %} + {%- endif %} + + {%- if last_updated %} + {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %} + {%- endif %} +

+
+ + {% trans %}Sphinx theme provided by Read the Docs{% endtrans %} +
diff --git a/docs/_themes/sphinx_rtd_theme/layout.html b/docs/_themes/sphinx_rtd_theme/layout.html new file mode 100644 index 0000000..552c77f --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/layout.html @@ -0,0 +1,161 @@ +{# TEMPLATE VAR SETTINGS #} +{%- set url_root = pathto('', 1) %} +{%- if url_root == '#' %}{% set url_root = '' %}{% endif %} +{%- if not embedded and docstitle %} + {%- set titlesuffix = " — "|safe + docstitle|e %} +{%- else %} + {%- set titlesuffix = "" %} +{%- endif %} + + + + + + + + {% block htmltitle %} + {{ title|striptags|e }}{{ titlesuffix }} + {% endblock %} + + {# FAVICON #} + {% if favicon %} + + {% endif %} + + {# CSS #} + + + {# JS #} + {% if not embedded %} + + + {%- for scriptfile in script_files %} + + {%- endfor %} + + {% if use_opensearch %} + + {% endif %} + + {% endif %} + + {# RTD hosts these file themselves, so just load on non RTD builds #} + {% if not READTHEDOCS %} + + + {% endif %} + + {# STICKY NAVIGATION #} + {% if theme_sticky_navigation %} + + {% endif %} + + {% for cssfile in css_files %} + + {% endfor %} + + {%- block linktags %} + {%- if hasdoc('about') %} + + {%- endif %} + {%- if hasdoc('genindex') %} + + {%- endif %} + {%- if hasdoc('search') %} + + {%- endif %} + {%- if hasdoc('copyright') %} + + {%- endif %} + + {%- if parents %} + + {%- endif %} + {%- if next %} + + {%- endif %} + {%- if prev %} + + {%- endif %} + {%- endblock %} + {%- block extrahead %} {% endblock %} + + + + + + + +
+ + {# SIDE NAV, TOGGLES ON MOBILE #} + + +
+ + {# MOBILE NAV, TRIGGLES SIDE NAV ON TOGGLE #} + + + + {# PAGE CONTENT #} +
+
+ {% include "breadcrumbs.html" %} +
+ {% block body %}{% endblock %} +
+ {% include "footer.html" %} +
+
+ +
+ +
+ {% include "versions.html" %} + + {% if theme_github_fork %} + Fork me on GitHub + {% endif %} + + + diff --git a/docs/_themes/sphinx_rtd_theme/layout_old.html b/docs/_themes/sphinx_rtd_theme/layout_old.html new file mode 100644 index 0000000..deb8df2 --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/layout_old.html @@ -0,0 +1,205 @@ +{# + basic/layout.html + ~~~~~~~~~~~~~~~~~ + + Master layout template for Sphinx themes. + + :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +#} +{%- block doctype -%} + +{%- endblock %} +{%- set reldelim1 = reldelim1 is not defined and ' »' or reldelim1 %} +{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %} +{%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and + (sidebars != []) %} +{%- set url_root = pathto('', 1) %} +{# XXX necessary? #} +{%- if url_root == '#' %}{% set url_root = '' %}{% endif %} +{%- if not embedded and docstitle %} + {%- set titlesuffix = " — "|safe + docstitle|e %} +{%- else %} + {%- set titlesuffix = "" %} +{%- endif %} + +{%- macro relbar() %} + +{%- endmacro %} + +{%- macro sidebar() %} + {%- if render_sidebar %} +
+
+ {%- block sidebarlogo %} + {%- if logo %} + + {%- endif %} + {%- endblock %} + {%- if sidebars != None %} + {#- new style sidebar: explicitly include/exclude templates #} + {%- for sidebartemplate in sidebars %} + {%- include sidebartemplate %} + {%- endfor %} + {%- else %} + {#- old style sidebars: using blocks -- should be deprecated #} + {%- block sidebartoc %} + {%- include "localtoc.html" %} + {%- endblock %} + {%- block sidebarrel %} + {%- include "relations.html" %} + {%- endblock %} + {%- block sidebarsourcelink %} + {%- include "sourcelink.html" %} + {%- endblock %} + {%- if customsidebar %} + {%- include customsidebar %} + {%- endif %} + {%- block sidebarsearch %} + {%- include "searchbox.html" %} + {%- endblock %} + {%- endif %} +
+
+ {%- endif %} +{%- endmacro %} + +{%- macro script() %} + + {%- for scriptfile in script_files %} + + {%- endfor %} +{%- endmacro %} + +{%- macro css() %} + + + {%- for cssfile in css_files %} + + {%- endfor %} +{%- endmacro %} + + + + + {{ metatags }} + {%- block htmltitle %} + {{ title|striptags|e }}{{ titlesuffix }} + {%- endblock %} + {{ css() }} + {%- if not embedded %} + {{ script() }} + {%- if use_opensearch %} + + {%- endif %} + {%- if favicon %} + + {%- endif %} + {%- endif %} +{%- block linktags %} + {%- if hasdoc('about') %} + + {%- endif %} + {%- if hasdoc('genindex') %} + + {%- endif %} + {%- if hasdoc('search') %} + + {%- endif %} + {%- if hasdoc('copyright') %} + + {%- endif %} + + {%- if parents %} + + {%- endif %} + {%- if next %} + + {%- endif %} + {%- if prev %} + + {%- endif %} +{%- endblock %} +{%- block extrahead %} {% endblock %} + + +{%- block header %}{% endblock %} + +{%- block relbar1 %}{{ relbar() }}{% endblock %} + +{%- block content %} + {%- block sidebar1 %} {# possible location for sidebar #} {% endblock %} + +
+ {%- block document %} +
+ {%- if render_sidebar %} +
+ {%- endif %} +
+ {% block body %} {% endblock %} +
+ {%- if render_sidebar %} +
+ {%- endif %} +
+ {%- endblock %} + + {%- block sidebar2 %}{{ sidebar() }}{% endblock %} +
+
+{%- endblock %} + +{%- block relbar2 %}{{ relbar() }}{% endblock %} + +{%- block footer %} + +

asdf asdf asdf asdf 22

+{%- endblock %} + + + diff --git a/docs/_themes/sphinx_rtd_theme/search.html b/docs/_themes/sphinx_rtd_theme/search.html new file mode 100644 index 0000000..d8bbe69 --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/search.html @@ -0,0 +1,50 @@ +{# + basic/search.html + ~~~~~~~~~~~~~~~~~ + + Template for the search page. + + :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +#} +{%- extends "layout.html" %} +{% set title = _('Search') %} +{% set script_files = script_files + ['_static/searchtools.js'] %} +{% block extrahead %} + + {# this is used when loading the search index using $.ajax fails, + such as on Chrome for documents on localhost #} + + {{ super() }} +{% endblock %} +{% block body %} + + + {% if search_performed %} +

{{ _('Search Results') }}

+ {% if not search_results %} +

{{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}

+ {% endif %} + {% endif %} +
+ {% if search_results %} +
    + {% for href, caption, context in search_results %} +
  • + {{ caption }} +

    {{ context|e }}

    +
  • + {% endfor %} +
+ {% endif %} +
+{% endblock %} diff --git a/docs/_themes/sphinx_rtd_theme/searchbox.html b/docs/_themes/sphinx_rtd_theme/searchbox.html new file mode 100644 index 0000000..24418d3 --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/searchbox.html @@ -0,0 +1,7 @@ +
+
+ + + + +
diff --git a/docs/_themes/sphinx_rtd_theme/static/css/badge_only.css b/docs/_themes/sphinx_rtd_theme/static/css/badge_only.css new file mode 100644 index 0000000..6f7bbe7 --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/static/css/badge_only.css @@ -0,0 +1,224 @@ +.font-smooth, .fa:before { + -webkit-font-smoothing: antialiased; +} + +.clearfix { + *zoom: 1; +} +.clearfix:before, .clearfix:after { + display: table; + content: ""; +} +.clearfix:after { + clear: both; +} + +@font-face { + font-family: FontAwesome; + font-weight: normal; + font-style: normal; + src: url("../font/fontawesome_webfont.eot"); + src: url("../font/fontawesome_webfont.eot?#iefix") format("embedded-opentype"), url("../font/fontawesome_webfont.woff") format("woff"), url("../font/fontawesome_webfont.ttf") format("truetype"), url("../font/fontawesome_webfont.svg#FontAwesome") format("svg"); +} + +.fa:before { + display: inline-block; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + line-height: 1; + text-decoration: inherit; +} + +a .fa { + display: inline-block; + text-decoration: inherit; +} + +li .fa { + display: inline-block; +} +li .fa-large:before, +li .fa-large:before { + /* 1.5 increased font size for fa-large * 1.25 width */ + width: 1.875em; +} + +ul.fas { + list-style-type: none; + margin-left: 2em; + text-indent: -0.8em; +} +ul.fas li .fa { + width: 0.8em; +} +ul.fas li .fa-large:before, +ul.fas li .fa-large:before { + /* 1.5 increased font size for fa-large * 1.25 width */ + vertical-align: baseline; +} + +.fa-book:before { + content: "\f02d"; +} + +.icon-book:before { + content: "\f02d"; +} + +.fa-caret-down:before { + content: "\f0d7"; +} + +.icon-caret-down:before { + content: "\f0d7"; +} + +.fa-caret-up:before { + content: "\f0d8"; +} + +.icon-caret-up:before { + content: "\f0d8"; +} + +.fa-caret-left:before { + content: "\f0d9"; +} + +.icon-caret-left:before { + content: "\f0d9"; +} + +.fa-caret-right:before { + content: "\f0da"; +} + +.icon-caret-right:before { + content: "\f0da"; +} + +.rst-versions { + position: fixed; + bottom: 0; + left: 0; + width: 300px; + color: #fcfcfc; + background: #1f1d1d; + border-top: solid 10px #343131; + font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; + z-index: 400; +} +.rst-versions a { + color: #2980b9; + text-decoration: none; +} +.rst-versions .rst-badge-small { + display: none; +} +.rst-versions .rst-current-version { + padding: 12px; + background-color: #272525; + display: block; + text-align: right; + font-size: 90%; + cursor: pointer; + color: #27ae60; + *zoom: 1; +} +.rst-versions .rst-current-version:before, .rst-versions .rst-current-version:after { + display: table; + content: ""; +} +.rst-versions .rst-current-version:after { + clear: both; +} +.rst-versions .rst-current-version .fa { + color: #fcfcfc; +} +.rst-versions .rst-current-version .fa-book { + float: left; +} +.rst-versions .rst-current-version .icon-book { + float: left; +} +.rst-versions .rst-current-version.rst-out-of-date { + background-color: #e74c3c; + color: white; +} +.rst-versions .rst-current-version.rst-active-old-version { + background-color: #f1c40f; + color: black; +} +.rst-versions.shift-up .rst-other-versions { + display: block; +} +.rst-versions .rst-other-versions { + font-size: 90%; + padding: 12px; + color: gray; + display: none; +} +.rst-versions .rst-other-versions hr { + display: block; + height: 1px; + border: 0; + margin: 20px 0; + padding: 0; + border-top: solid 1px #413d3d; +} +.rst-versions .rst-other-versions dd { + display: inline-block; + margin: 0; +} +.rst-versions .rst-other-versions dd a { + display: inline-block; + padding: 6px; + color: #fcfcfc; +} +.rst-versions.rst-badge { + width: auto; + bottom: 20px; + right: 20px; + left: auto; + border: none; + max-width: 300px; +} +.rst-versions.rst-badge .icon-book { + float: none; +} +.rst-versions.rst-badge .fa-book { + float: none; +} +.rst-versions.rst-badge.shift-up .rst-current-version { + text-align: right; +} +.rst-versions.rst-badge.shift-up .rst-current-version .fa-book { + float: left; +} +.rst-versions.rst-badge.shift-up .rst-current-version .icon-book { + float: left; +} +.rst-versions.rst-badge .rst-current-version { + width: auto; + height: 30px; + line-height: 30px; + padding: 0 6px; + display: block; + text-align: center; +} + +@media screen and (max-width: 768px) { + .rst-versions { + width: 85%; + display: none; + } + .rst-versions.shift { + display: block; + } + + img { + width: 100%; + height: auto; + } +} diff --git a/docs/_themes/sphinx_rtd_theme/static/css/theme.css b/docs/_themes/sphinx_rtd_theme/static/css/theme.css new file mode 100644 index 0000000..9f485d0 --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/static/css/theme.css @@ -0,0 +1,4725 @@ +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { + display: block; +} + +audio, canvas, video { + display: inline-block; + *display: inline; + *zoom: 1; +} + +audio:not([controls]) { + display: none; +} + +[hidden] { + display: none; +} + +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +html { + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +body { + margin: 0; +} + +a:hover, a:active { + outline: 0; +} + +abbr[title] { + border-bottom: 1px dotted; +} + +b, strong { + font-weight: bold; +} + +blockquote { + margin: 0; +} + +dfn { + font-style: italic; +} + +hr { + display: block; + height: 1px; + border: 0; + border-top: 1px solid #cccccc; + margin: 20px 0; + padding: 0; +} + +ins { + background: #ffff99; + color: black; + text-decoration: none; +} + +mark { + background: yellow; + color: black; + font-style: italic; + font-weight: bold; +} + +pre, code, .rst-content tt, kbd, samp { + font-family: monospace, serif; + _font-family: "courier new", monospace; + font-size: 1em; +} + +pre { + white-space: pre; +} + +q { + quotes: none; +} + +q:before, q:after { + content: ""; + content: none; +} + +small { + font-size: 85%; +} + +sub, sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +ul, ol, dl { + margin: 0; + padding: 0; + list-style: none; + list-style-image: none; +} + +li { + list-style: none; +} + +dd { + margin: 0; +} + +img { + border: 0; + -ms-interpolation-mode: bicubic; + vertical-align: middle; + max-width: 100%; +} + +svg:not(:root) { + overflow: hidden; +} + +figure { + margin: 0; +} + +form { + margin: 0; +} + +fieldset { + border: 0; + margin: 0; + padding: 0; +} + +label { + cursor: pointer; +} + +legend { + border: 0; + *margin-left: -7px; + padding: 0; + white-space: normal; +} + +button, input, select, textarea { + font-size: 100%; + margin: 0; + vertical-align: baseline; + *vertical-align: middle; +} + +button, input { + line-height: normal; +} + +button, input[type="button"], input[type="reset"], input[type="submit"] { + cursor: pointer; + -webkit-appearance: button; + *overflow: visible; +} + +button[disabled], input[disabled] { + cursor: default; +} + +input[type="checkbox"], input[type="radio"] { + box-sizing: border-box; + padding: 0; + *width: 13px; + *height: 13px; +} + +input[type="search"] { + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} + +input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none; +} + +button::-moz-focus-inner, input::-moz-focus-inner { + border: 0; + padding: 0; +} + +textarea { + overflow: auto; + vertical-align: top; + resize: vertical; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +td { + vertical-align: top; +} + +.chromeframe { + margin: 0.2em 0; + background: #cccccc; + color: black; + padding: 0.2em 0; +} + +.ir { + display: block; + border: 0; + text-indent: -999em; + overflow: hidden; + background-color: transparent; + background-repeat: no-repeat; + text-align: left; + direction: ltr; + *line-height: 0; +} + +.ir br { + display: none; +} + +.hidden { + display: none !important; + visibility: hidden; +} + +.visuallyhidden { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} + +.visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { + clip: auto; + height: auto; + margin: 0; + overflow: visible; + position: static; + width: auto; +} + +.invisible { + visibility: hidden; +} + +.relative { + position: relative; +} + +big, small { + font-size: 100%; +} + +@media print { + html, body, section { + background: none !important; + } + + * { + box-shadow: none !important; + text-shadow: none !important; + filter: none !important; + -ms-filter: none !important; + } + + a, a:visited { + text-decoration: underline; + } + + .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { + content: ""; + } + + pre, blockquote { + page-break-inside: avoid; + } + + thead { + display: table-header-group; + } + + tr, img { + page-break-inside: avoid; + } + + img { + max-width: 100% !important; + } + + @page { + margin: 0.5cm; +} + + p, h2, h3 { + orphans: 3; + widows: 3; + } + + h2, h3 { + page-break-after: avoid; + } +} +.font-smooth, .wy-alert, .rst-content .note, .rst-content .attention, .rst-content .caution, .rst-content .danger, .rst-content .error, .rst-content .hint, .rst-content .important, .rst-content .tip, .rst-content .warning, .rst-content .seealso, .btn, input[type="text"], input[type="password"], input[type="email"], input[type="url"], input[type="date"], input[type="month"], input[type="time"], input[type="datetime"], input[type="datetime-local"], input[type="week"], input[type="number"], input[type="search"], input[type="tel"], input[type="color"], select, textarea, .wy-tag-input-group, .wy-menu-vertical li.on a, .wy-menu-vertical li.current > a, .wy-side-nav-search > a, .wy-side-nav-search .wy-dropdown > a, .wy-nav-top a { + -webkit-font-smoothing: antialiased; +} + +.clearfix { + *zoom: 1; +} +.clearfix:before, .clearfix:after { + display: table; + content: ""; +} +.clearfix:after { + clear: both; +} + +/*! + * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */ +/* FONT PATH + * -------------------------- */ +@font-face { + font-family: 'FontAwesome'; + src: url("../fonts/fontawesome-webfont.eot?v=4.0.3"); + src: url("../fonts/fontawesome-webfont.eot?#iefix&v=4.0.3") format("embedded-opentype"), url("../fonts/fontawesome-webfont.woff?v=4.0.3") format("woff"), url("../fonts/fontawesome-webfont.ttf?v=4.0.3") format("truetype"), url("../fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular") format("svg"); + font-weight: normal; + font-style: normal; +} + +.fa, .wy-dropdown .caret, .wy-inline-validate.wy-inline-validate-success .wy-input-context, .wy-inline-validate.wy-inline-validate-danger .wy-input-context, .wy-inline-validate.wy-inline-validate-warning .wy-input-context, .wy-inline-validate.wy-inline-validate-info .wy-input-context, .wy-tag-input-group .wy-tag .wy-tag-remove, .rst-content .admonition-title, .rst-content h1 .headerlink, .rst-content h2 .headerlink, .rst-content h3 .headerlink, .rst-content h4 .headerlink, .rst-content h5 .headerlink, .rst-content h6 .headerlink, .rst-content dl dt .headerlink, .icon { + display: inline-block; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* makes the font 33% larger relative to the icon container */ +.fa-lg { + font-size: 1.33333em; + line-height: 0.75em; + vertical-align: -15%; +} + +.fa-2x { + font-size: 2em; +} + +.fa-3x { + font-size: 3em; +} + +.fa-4x { + font-size: 4em; +} + +.fa-5x { + font-size: 5em; +} + +.fa-fw { + width: 1.28571em; + text-align: center; +} + +.fa-ul { + padding-left: 0; + margin-left: 2.14286em; + list-style-type: none; +} +.fa-ul > li { + position: relative; +} + +.fa-li { + position: absolute; + left: -2.14286em; + width: 2.14286em; + top: 0.14286em; + text-align: center; +} +.fa-li.fa-lg { + left: -1.85714em; +} + +.fa-border { + padding: .2em .25em .15em; + border: solid 0.08em #eeeeee; + border-radius: .1em; +} + +.pull-right { + float: right; +} + +.pull-left { + float: left; +} + +.fa.pull-left, .wy-dropdown .pull-left.caret, .wy-inline-validate.wy-inline-validate-success .pull-left.wy-input-context, .wy-inline-validate.wy-inline-validate-danger .pull-left.wy-input-context, .wy-inline-validate.wy-inline-validate-warning .pull-left.wy-input-context, .wy-inline-validate.wy-inline-validate-info .pull-left.wy-input-context, .wy-tag-input-group .wy-tag .pull-left.wy-tag-remove, .rst-content .pull-left.admonition-title, .rst-content h1 .pull-left.headerlink, .rst-content h2 .pull-left.headerlink, .rst-content h3 .pull-left.headerlink, .rst-content h4 .pull-left.headerlink, .rst-content h5 .pull-left.headerlink, .rst-content h6 .pull-left.headerlink, .rst-content dl dt .pull-left.headerlink, .pull-left.icon { + margin-right: .3em; +} +.fa.pull-right, .wy-dropdown .pull-right.caret, .wy-inline-validate.wy-inline-validate-success .pull-right.wy-input-context, .wy-inline-validate.wy-inline-validate-danger .pull-right.wy-input-context, .wy-inline-validate.wy-inline-validate-warning .pull-right.wy-input-context, .wy-inline-validate.wy-inline-validate-info .pull-right.wy-input-context, .wy-tag-input-group .wy-tag .pull-right.wy-tag-remove, .rst-content .pull-right.admonition-title, .rst-content h1 .pull-right.headerlink, .rst-content h2 .pull-right.headerlink, .rst-content h3 .pull-right.headerlink, .rst-content h4 .pull-right.headerlink, .rst-content h5 .pull-right.headerlink, .rst-content h6 .pull-right.headerlink, .rst-content dl dt .pull-right.headerlink, .pull-right.icon { + margin-left: .3em; +} + +.fa-spin { + -webkit-animation: spin 2s infinite linear; + -moz-animation: spin 2s infinite linear; + -o-animation: spin 2s infinite linear; + animation: spin 2s infinite linear; +} + +@-moz-keyframes spin { + 0% { + -moz-transform: rotate(0deg); + } + + 100% { + -moz-transform: rotate(359deg); + } +} + +@-webkit-keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + } + + 100% { + -webkit-transform: rotate(359deg); + } +} + +@-o-keyframes spin { + 0% { + -o-transform: rotate(0deg); + } + + 100% { + -o-transform: rotate(359deg); + } +} + +@-ms-keyframes spin { + 0% { + -ms-transform: rotate(0deg); + } + + 100% { + -ms-transform: rotate(359deg); + } +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(359deg); + } +} + +.fa-rotate-90 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation); + -webkit-transform: rotate(90deg); + -moz-transform: rotate(90deg); + -ms-transform: rotate(90deg); + -o-transform: rotate(90deg); + transform: rotate(90deg); +} + +.fa-rotate-180 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation); + -webkit-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -o-transform: rotate(180deg); + transform: rotate(180deg); +} + +.fa-rotate-270 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation); + -webkit-transform: rotate(270deg); + -moz-transform: rotate(270deg); + -ms-transform: rotate(270deg); + -o-transform: rotate(270deg); + transform: rotate(270deg); +} + +.fa-flip-horizontal { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation); + -webkit-transform: scale(-1, 1); + -moz-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + -o-transform: scale(-1, 1); + transform: scale(-1, 1); +} + +.fa-flip-vertical { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation); + -webkit-transform: scale(1, -1); + -moz-transform: scale(1, -1); + -ms-transform: scale(1, -1); + -o-transform: scale(1, -1); + transform: scale(1, -1); +} + +.fa-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle; +} + +.fa-stack-1x, .fa-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center; +} + +.fa-stack-1x { + line-height: inherit; +} + +.fa-stack-2x { + font-size: 2em; +} + +.fa-inverse { + color: white; +} + +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen + readers do not read off random characters that represent icons */ +.fa-glass:before { + content: "\f000"; +} + +.fa-music:before { + content: "\f001"; +} + +.fa-search:before, .icon-search:before { + content: "\f002"; +} + +.fa-envelope-o:before { + content: "\f003"; +} + +.fa-heart:before { + content: "\f004"; +} + +.fa-star:before { + content: "\f005"; +} + +.fa-star-o:before { + content: "\f006"; +} + +.fa-user:before { + content: "\f007"; +} + +.fa-film:before { + content: "\f008"; +} + +.fa-th-large:before { + content: "\f009"; +} + +.fa-th:before { + content: "\f00a"; +} + +.fa-th-list:before { + content: "\f00b"; +} + +.fa-check:before { + content: "\f00c"; +} + +.fa-times:before, .wy-tag-input-group .wy-tag .wy-tag-remove:before { + content: "\f00d"; +} + +.fa-search-plus:before { + content: "\f00e"; +} + +.fa-search-minus:before { + content: "\f010"; +} + +.fa-power-off:before { + content: "\f011"; +} + +.fa-signal:before { + content: "\f012"; +} + +.fa-gear:before, +.fa-cog:before { + content: "\f013"; +} + +.fa-trash-o:before { + content: "\f014"; +} + +.fa-home:before, .icon-home:before { + content: "\f015"; +} + +.fa-file-o:before { + content: "\f016"; +} + +.fa-clock-o:before { + content: "\f017"; +} + +.fa-road:before { + content: "\f018"; +} + +.fa-download:before { + content: "\f019"; +} + +.fa-arrow-circle-o-down:before { + content: "\f01a"; +} + +.fa-arrow-circle-o-up:before { + content: "\f01b"; +} + +.fa-inbox:before { + content: "\f01c"; +} + +.fa-play-circle-o:before { + content: "\f01d"; +} + +.fa-rotate-right:before, +.fa-repeat:before { + content: "\f01e"; +} + +.fa-refresh:before { + content: "\f021"; +} + +.fa-list-alt:before { + content: "\f022"; +} + +.fa-lock:before { + content: "\f023"; +} + +.fa-flag:before { + content: "\f024"; +} + +.fa-headphones:before { + content: "\f025"; +} + +.fa-volume-off:before { + content: "\f026"; +} + +.fa-volume-down:before { + content: "\f027"; +} + +.fa-volume-up:before { + content: "\f028"; +} + +.fa-qrcode:before { + content: "\f029"; +} + +.fa-barcode:before { + content: "\f02a"; +} + +.fa-tag:before { + content: "\f02b"; +} + +.fa-tags:before { + content: "\f02c"; +} + +.fa-book:before, .icon-book:before { + content: "\f02d"; +} + +.fa-bookmark:before { + content: "\f02e"; +} + +.fa-print:before { + content: "\f02f"; +} + +.fa-camera:before { + content: "\f030"; +} + +.fa-font:before { + content: "\f031"; +} + +.fa-bold:before { + content: "\f032"; +} + +.fa-italic:before { + content: "\f033"; +} + +.fa-text-height:before { + content: "\f034"; +} + +.fa-text-width:before { + content: "\f035"; +} + +.fa-align-left:before { + content: "\f036"; +} + +.fa-align-center:before { + content: "\f037"; +} + +.fa-align-right:before { + content: "\f038"; +} + +.fa-align-justify:before { + content: "\f039"; +} + +.fa-list:before { + content: "\f03a"; +} + +.fa-dedent:before, +.fa-outdent:before { + content: "\f03b"; +} + +.fa-indent:before { + content: "\f03c"; +} + +.fa-video-camera:before { + content: "\f03d"; +} + +.fa-picture-o:before { + content: "\f03e"; +} + +.fa-pencil:before { + content: "\f040"; +} + +.fa-map-marker:before { + content: "\f041"; +} + +.fa-adjust:before { + content: "\f042"; +} + +.fa-tint:before { + content: "\f043"; +} + +.fa-edit:before, +.fa-pencil-square-o:before { + content: "\f044"; +} + +.fa-share-square-o:before { + content: "\f045"; +} + +.fa-check-square-o:before { + content: "\f046"; +} + +.fa-arrows:before { + content: "\f047"; +} + +.fa-step-backward:before { + content: "\f048"; +} + +.fa-fast-backward:before { + content: "\f049"; +} + +.fa-backward:before { + content: "\f04a"; +} + +.fa-play:before { + content: "\f04b"; +} + +.fa-pause:before { + content: "\f04c"; +} + +.fa-stop:before { + content: "\f04d"; +} + +.fa-forward:before { + content: "\f04e"; +} + +.fa-fast-forward:before { + content: "\f050"; +} + +.fa-step-forward:before { + content: "\f051"; +} + +.fa-eject:before { + content: "\f052"; +} + +.fa-chevron-left:before { + content: "\f053"; +} + +.fa-chevron-right:before { + content: "\f054"; +} + +.fa-plus-circle:before { + content: "\f055"; +} + +.fa-minus-circle:before { + content: "\f056"; +} + +.fa-times-circle:before { + content: "\f057"; +} + +.fa-check-circle:before, .wy-inline-validate.wy-inline-validate-success .wy-input-context:before { + content: "\f058"; +} + +.fa-question-circle:before { + content: "\f059"; +} + +.fa-info-circle:before { + content: "\f05a"; +} + +.fa-crosshairs:before { + content: "\f05b"; +} + +.fa-times-circle-o:before, .wy-inline-validate.wy-inline-validate-danger .wy-input-context:before { + content: "\f05c"; +} + +.fa-check-circle-o:before { + content: "\f05d"; +} + +.fa-ban:before { + content: "\f05e"; +} + +.fa-arrow-left:before { + content: "\f060"; +} + +.fa-arrow-right:before { + content: "\f061"; +} + +.fa-arrow-up:before { + content: "\f062"; +} + +.fa-arrow-down:before { + content: "\f063"; +} + +.fa-mail-forward:before, +.fa-share:before { + content: "\f064"; +} + +.fa-expand:before { + content: "\f065"; +} + +.fa-compress:before { + content: "\f066"; +} + +.fa-plus:before { + content: "\f067"; +} + +.fa-minus:before { + content: "\f068"; +} + +.fa-asterisk:before { + content: "\f069"; +} + +.fa-exclamation-circle:before, .wy-inline-validate.wy-inline-validate-warning .wy-input-context:before, .wy-inline-validate.wy-inline-validate-info .wy-input-context:before, .rst-content .admonition-title:before { + content: "\f06a"; +} + +.fa-gift:before { + content: "\f06b"; +} + +.fa-leaf:before { + content: "\f06c"; +} + +.fa-fire:before, .icon-fire:before { + content: "\f06d"; +} + +.fa-eye:before { + content: "\f06e"; +} + +.fa-eye-slash:before { + content: "\f070"; +} + +.fa-warning:before, +.fa-exclamation-triangle:before { + content: "\f071"; +} + +.fa-plane:before { + content: "\f072"; +} + +.fa-calendar:before { + content: "\f073"; +} + +.fa-random:before { + content: "\f074"; +} + +.fa-comment:before { + content: "\f075"; +} + +.fa-magnet:before { + content: "\f076"; +} + +.fa-chevron-up:before { + content: "\f077"; +} + +.fa-chevron-down:before { + content: "\f078"; +} + +.fa-retweet:before { + content: "\f079"; +} + +.fa-shopping-cart:before { + content: "\f07a"; +} + +.fa-folder:before { + content: "\f07b"; +} + +.fa-folder-open:before { + content: "\f07c"; +} + +.fa-arrows-v:before { + content: "\f07d"; +} + +.fa-arrows-h:before { + content: "\f07e"; +} + +.fa-bar-chart-o:before { + content: "\f080"; +} + +.fa-twitter-square:before { + content: "\f081"; +} + +.fa-facebook-square:before { + content: "\f082"; +} + +.fa-camera-retro:before { + content: "\f083"; +} + +.fa-key:before { + content: "\f084"; +} + +.fa-gears:before, +.fa-cogs:before { + content: "\f085"; +} + +.fa-comments:before { + content: "\f086"; +} + +.fa-thumbs-o-up:before { + content: "\f087"; +} + +.fa-thumbs-o-down:before { + content: "\f088"; +} + +.fa-star-half:before { + content: "\f089"; +} + +.fa-heart-o:before { + content: "\f08a"; +} + +.fa-sign-out:before { + content: "\f08b"; +} + +.fa-linkedin-square:before { + content: "\f08c"; +} + +.fa-thumb-tack:before { + content: "\f08d"; +} + +.fa-external-link:before { + content: "\f08e"; +} + +.fa-sign-in:before { + content: "\f090"; +} + +.fa-trophy:before { + content: "\f091"; +} + +.fa-github-square:before { + content: "\f092"; +} + +.fa-upload:before { + content: "\f093"; +} + +.fa-lemon-o:before { + content: "\f094"; +} + +.fa-phone:before { + content: "\f095"; +} + +.fa-square-o:before { + content: "\f096"; +} + +.fa-bookmark-o:before { + content: "\f097"; +} + +.fa-phone-square:before { + content: "\f098"; +} + +.fa-twitter:before { + content: "\f099"; +} + +.fa-facebook:before { + content: "\f09a"; +} + +.fa-github:before, .icon-github:before { + content: "\f09b"; +} + +.fa-unlock:before { + content: "\f09c"; +} + +.fa-credit-card:before { + content: "\f09d"; +} + +.fa-rss:before { + content: "\f09e"; +} + +.fa-hdd-o:before { + content: "\f0a0"; +} + +.fa-bullhorn:before { + content: "\f0a1"; +} + +.fa-bell:before { + content: "\f0f3"; +} + +.fa-certificate:before { + content: "\f0a3"; +} + +.fa-hand-o-right:before { + content: "\f0a4"; +} + +.fa-hand-o-left:before { + content: "\f0a5"; +} + +.fa-hand-o-up:before { + content: "\f0a6"; +} + +.fa-hand-o-down:before { + content: "\f0a7"; +} + +.fa-arrow-circle-left:before, .icon-circle-arrow-left:before { + content: "\f0a8"; +} + +.fa-arrow-circle-right:before, .icon-circle-arrow-right:before { + content: "\f0a9"; +} + +.fa-arrow-circle-up:before { + content: "\f0aa"; +} + +.fa-arrow-circle-down:before { + content: "\f0ab"; +} + +.fa-globe:before { + content: "\f0ac"; +} + +.fa-wrench:before { + content: "\f0ad"; +} + +.fa-tasks:before { + content: "\f0ae"; +} + +.fa-filter:before { + content: "\f0b0"; +} + +.fa-briefcase:before { + content: "\f0b1"; +} + +.fa-arrows-alt:before { + content: "\f0b2"; +} + +.fa-group:before, +.fa-users:before { + content: "\f0c0"; +} + +.fa-chain:before, +.fa-link:before, +.icon-link:before { + content: "\f0c1"; +} + +.fa-cloud:before { + content: "\f0c2"; +} + +.fa-flask:before { + content: "\f0c3"; +} + +.fa-cut:before, +.fa-scissors:before { + content: "\f0c4"; +} + +.fa-copy:before, +.fa-files-o:before { + content: "\f0c5"; +} + +.fa-paperclip:before { + content: "\f0c6"; +} + +.fa-save:before, +.fa-floppy-o:before { + content: "\f0c7"; +} + +.fa-square:before { + content: "\f0c8"; +} + +.fa-bars:before { + content: "\f0c9"; +} + +.fa-list-ul:before { + content: "\f0ca"; +} + +.fa-list-ol:before { + content: "\f0cb"; +} + +.fa-strikethrough:before { + content: "\f0cc"; +} + +.fa-underline:before { + content: "\f0cd"; +} + +.fa-table:before { + content: "\f0ce"; +} + +.fa-magic:before { + content: "\f0d0"; +} + +.fa-truck:before { + content: "\f0d1"; +} + +.fa-pinterest:before { + content: "\f0d2"; +} + +.fa-pinterest-square:before { + content: "\f0d3"; +} + +.fa-google-plus-square:before { + content: "\f0d4"; +} + +.fa-google-plus:before { + content: "\f0d5"; +} + +.fa-money:before { + content: "\f0d6"; +} + +.fa-caret-down:before, .wy-dropdown .caret:before, .icon-caret-down:before { + content: "\f0d7"; +} + +.fa-caret-up:before { + content: "\f0d8"; +} + +.fa-caret-left:before { + content: "\f0d9"; +} + +.fa-caret-right:before { + content: "\f0da"; +} + +.fa-columns:before { + content: "\f0db"; +} + +.fa-unsorted:before, +.fa-sort:before { + content: "\f0dc"; +} + +.fa-sort-down:before, +.fa-sort-asc:before { + content: "\f0dd"; +} + +.fa-sort-up:before, +.fa-sort-desc:before { + content: "\f0de"; +} + +.fa-envelope:before { + content: "\f0e0"; +} + +.fa-linkedin:before { + content: "\f0e1"; +} + +.fa-rotate-left:before, +.fa-undo:before { + content: "\f0e2"; +} + +.fa-legal:before, +.fa-gavel:before { + content: "\f0e3"; +} + +.fa-dashboard:before, +.fa-tachometer:before { + content: "\f0e4"; +} + +.fa-comment-o:before { + content: "\f0e5"; +} + +.fa-comments-o:before { + content: "\f0e6"; +} + +.fa-flash:before, +.fa-bolt:before { + content: "\f0e7"; +} + +.fa-sitemap:before { + content: "\f0e8"; +} + +.fa-umbrella:before { + content: "\f0e9"; +} + +.fa-paste:before, +.fa-clipboard:before { + content: "\f0ea"; +} + +.fa-lightbulb-o:before { + content: "\f0eb"; +} + +.fa-exchange:before { + content: "\f0ec"; +} + +.fa-cloud-download:before { + content: "\f0ed"; +} + +.fa-cloud-upload:before { + content: "\f0ee"; +} + +.fa-user-md:before { + content: "\f0f0"; +} + +.fa-stethoscope:before { + content: "\f0f1"; +} + +.fa-suitcase:before { + content: "\f0f2"; +} + +.fa-bell-o:before { + content: "\f0a2"; +} + +.fa-coffee:before { + content: "\f0f4"; +} + +.fa-cutlery:before { + content: "\f0f5"; +} + +.fa-file-text-o:before { + content: "\f0f6"; +} + +.fa-building-o:before { + content: "\f0f7"; +} + +.fa-hospital-o:before { + content: "\f0f8"; +} + +.fa-ambulance:before { + content: "\f0f9"; +} + +.fa-medkit:before { + content: "\f0fa"; +} + +.fa-fighter-jet:before { + content: "\f0fb"; +} + +.fa-beer:before { + content: "\f0fc"; +} + +.fa-h-square:before { + content: "\f0fd"; +} + +.fa-plus-square:before { + content: "\f0fe"; +} + +.fa-angle-double-left:before { + content: "\f100"; +} + +.fa-angle-double-right:before { + content: "\f101"; +} + +.fa-angle-double-up:before { + content: "\f102"; +} + +.fa-angle-double-down:before { + content: "\f103"; +} + +.fa-angle-left:before { + content: "\f104"; +} + +.fa-angle-right:before { + content: "\f105"; +} + +.fa-angle-up:before { + content: "\f106"; +} + +.fa-angle-down:before { + content: "\f107"; +} + +.fa-desktop:before { + content: "\f108"; +} + +.fa-laptop:before { + content: "\f109"; +} + +.fa-tablet:before { + content: "\f10a"; +} + +.fa-mobile-phone:before, +.fa-mobile:before { + content: "\f10b"; +} + +.fa-circle-o:before { + content: "\f10c"; +} + +.fa-quote-left:before { + content: "\f10d"; +} + +.fa-quote-right:before { + content: "\f10e"; +} + +.fa-spinner:before { + content: "\f110"; +} + +.fa-circle:before { + content: "\f111"; +} + +.fa-mail-reply:before, +.fa-reply:before { + content: "\f112"; +} + +.fa-github-alt:before { + content: "\f113"; +} + +.fa-folder-o:before { + content: "\f114"; +} + +.fa-folder-open-o:before { + content: "\f115"; +} + +.fa-smile-o:before { + content: "\f118"; +} + +.fa-frown-o:before { + content: "\f119"; +} + +.fa-meh-o:before { + content: "\f11a"; +} + +.fa-gamepad:before { + content: "\f11b"; +} + +.fa-keyboard-o:before { + content: "\f11c"; +} + +.fa-flag-o:before { + content: "\f11d"; +} + +.fa-flag-checkered:before { + content: "\f11e"; +} + +.fa-terminal:before { + content: "\f120"; +} + +.fa-code:before { + content: "\f121"; +} + +.fa-reply-all:before { + content: "\f122"; +} + +.fa-mail-reply-all:before { + content: "\f122"; +} + +.fa-star-half-empty:before, +.fa-star-half-full:before, +.fa-star-half-o:before { + content: "\f123"; +} + +.fa-location-arrow:before { + content: "\f124"; +} + +.fa-crop:before { + content: "\f125"; +} + +.fa-code-fork:before { + content: "\f126"; +} + +.fa-unlink:before, +.fa-chain-broken:before { + content: "\f127"; +} + +.fa-question:before { + content: "\f128"; +} + +.fa-info:before { + content: "\f129"; +} + +.fa-exclamation:before { + content: "\f12a"; +} + +.fa-superscript:before { + content: "\f12b"; +} + +.fa-subscript:before { + content: "\f12c"; +} + +.fa-eraser:before { + content: "\f12d"; +} + +.fa-puzzle-piece:before { + content: "\f12e"; +} + +.fa-microphone:before { + content: "\f130"; +} + +.fa-microphone-slash:before { + content: "\f131"; +} + +.fa-shield:before { + content: "\f132"; +} + +.fa-calendar-o:before { + content: "\f133"; +} + +.fa-fire-extinguisher:before { + content: "\f134"; +} + +.fa-rocket:before { + content: "\f135"; +} + +.fa-maxcdn:before { + content: "\f136"; +} + +.fa-chevron-circle-left:before { + content: "\f137"; +} + +.fa-chevron-circle-right:before { + content: "\f138"; +} + +.fa-chevron-circle-up:before { + content: "\f139"; +} + +.fa-chevron-circle-down:before { + content: "\f13a"; +} + +.fa-html5:before { + content: "\f13b"; +} + +.fa-css3:before { + content: "\f13c"; +} + +.fa-anchor:before { + content: "\f13d"; +} + +.fa-unlock-alt:before { + content: "\f13e"; +} + +.fa-bullseye:before { + content: "\f140"; +} + +.fa-ellipsis-h:before { + content: "\f141"; +} + +.fa-ellipsis-v:before { + content: "\f142"; +} + +.fa-rss-square:before { + content: "\f143"; +} + +.fa-play-circle:before { + content: "\f144"; +} + +.fa-ticket:before { + content: "\f145"; +} + +.fa-minus-square:before { + content: "\f146"; +} + +.fa-minus-square-o:before { + content: "\f147"; +} + +.fa-level-up:before { + content: "\f148"; +} + +.fa-level-down:before { + content: "\f149"; +} + +.fa-check-square:before { + content: "\f14a"; +} + +.fa-pencil-square:before { + content: "\f14b"; +} + +.fa-external-link-square:before { + content: "\f14c"; +} + +.fa-share-square:before { + content: "\f14d"; +} + +.fa-compass:before { + content: "\f14e"; +} + +.fa-toggle-down:before, +.fa-caret-square-o-down:before { + content: "\f150"; +} + +.fa-toggle-up:before, +.fa-caret-square-o-up:before { + content: "\f151"; +} + +.fa-toggle-right:before, +.fa-caret-square-o-right:before { + content: "\f152"; +} + +.fa-euro:before, +.fa-eur:before { + content: "\f153"; +} + +.fa-gbp:before { + content: "\f154"; +} + +.fa-dollar:before, +.fa-usd:before { + content: "\f155"; +} + +.fa-rupee:before, +.fa-inr:before { + content: "\f156"; +} + +.fa-cny:before, +.fa-rmb:before, +.fa-yen:before, +.fa-jpy:before { + content: "\f157"; +} + +.fa-ruble:before, +.fa-rouble:before, +.fa-rub:before { + content: "\f158"; +} + +.fa-won:before, +.fa-krw:before { + content: "\f159"; +} + +.fa-bitcoin:before, +.fa-btc:before { + content: "\f15a"; +} + +.fa-file:before { + content: "\f15b"; +} + +.fa-file-text:before { + content: "\f15c"; +} + +.fa-sort-alpha-asc:before { + content: "\f15d"; +} + +.fa-sort-alpha-desc:before { + content: "\f15e"; +} + +.fa-sort-amount-asc:before { + content: "\f160"; +} + +.fa-sort-amount-desc:before { + content: "\f161"; +} + +.fa-sort-numeric-asc:before { + content: "\f162"; +} + +.fa-sort-numeric-desc:before { + content: "\f163"; +} + +.fa-thumbs-up:before { + content: "\f164"; +} + +.fa-thumbs-down:before { + content: "\f165"; +} + +.fa-youtube-square:before { + content: "\f166"; +} + +.fa-youtube:before { + content: "\f167"; +} + +.fa-xing:before { + content: "\f168"; +} + +.fa-xing-square:before { + content: "\f169"; +} + +.fa-youtube-play:before { + content: "\f16a"; +} + +.fa-dropbox:before { + content: "\f16b"; +} + +.fa-stack-overflow:before { + content: "\f16c"; +} + +.fa-instagram:before { + content: "\f16d"; +} + +.fa-flickr:before { + content: "\f16e"; +} + +.fa-adn:before { + content: "\f170"; +} + +.fa-bitbucket:before, .icon-bitbucket:before { + content: "\f171"; +} + +.fa-bitbucket-square:before { + content: "\f172"; +} + +.fa-tumblr:before { + content: "\f173"; +} + +.fa-tumblr-square:before { + content: "\f174"; +} + +.fa-long-arrow-down:before { + content: "\f175"; +} + +.fa-long-arrow-up:before { + content: "\f176"; +} + +.fa-long-arrow-left:before { + content: "\f177"; +} + +.fa-long-arrow-right:before { + content: "\f178"; +} + +.fa-apple:before { + content: "\f179"; +} + +.fa-windows:before { + content: "\f17a"; +} + +.fa-android:before { + content: "\f17b"; +} + +.fa-linux:before { + content: "\f17c"; +} + +.fa-dribbble:before { + content: "\f17d"; +} + +.fa-skype:before { + content: "\f17e"; +} + +.fa-foursquare:before { + content: "\f180"; +} + +.fa-trello:before { + content: "\f181"; +} + +.fa-female:before { + content: "\f182"; +} + +.fa-male:before { + content: "\f183"; +} + +.fa-gittip:before { + content: "\f184"; +} + +.fa-sun-o:before { + content: "\f185"; +} + +.fa-moon-o:before { + content: "\f186"; +} + +.fa-archive:before { + content: "\f187"; +} + +.fa-bug:before { + content: "\f188"; +} + +.fa-vk:before { + content: "\f189"; +} + +.fa-weibo:before { + content: "\f18a"; +} + +.fa-renren:before { + content: "\f18b"; +} + +.fa-pagelines:before { + content: "\f18c"; +} + +.fa-stack-exchange:before { + content: "\f18d"; +} + +.fa-arrow-circle-o-right:before { + content: "\f18e"; +} + +.fa-arrow-circle-o-left:before { + content: "\f190"; +} + +.fa-toggle-left:before, +.fa-caret-square-o-left:before { + content: "\f191"; +} + +.fa-dot-circle-o:before { + content: "\f192"; +} + +.fa-wheelchair:before { + content: "\f193"; +} + +.fa-vimeo-square:before { + content: "\f194"; +} + +.fa-turkish-lira:before, +.fa-try:before { + content: "\f195"; +} + +.fa-plus-square-o:before { + content: "\f196"; +} + +.btn .fa, .btn .wy-dropdown .caret, .wy-dropdown .btn .caret, .btn .wy-inline-validate.wy-inline-validate-success .wy-input-context, .wy-inline-validate.wy-inline-validate-success .btn .wy-input-context, .btn .wy-inline-validate.wy-inline-validate-danger .wy-input-context, .wy-inline-validate.wy-inline-validate-danger .btn .wy-input-context, .btn .wy-inline-validate.wy-inline-validate-warning .wy-input-context, .wy-inline-validate.wy-inline-validate-warning .btn .wy-input-context, .btn .wy-inline-validate.wy-inline-validate-info .wy-input-context, .wy-inline-validate.wy-inline-validate-info .btn .wy-input-context, .btn .wy-tag-input-group .wy-tag .wy-tag-remove, .wy-tag-input-group .wy-tag .btn .wy-tag-remove, .btn .rst-content .admonition-title, .rst-content .btn .admonition-title, .btn .rst-content h1 .headerlink, .rst-content h1 .btn .headerlink, .btn .rst-content h2 .headerlink, .rst-content h2 .btn .headerlink, .btn .rst-content h3 .headerlink, .rst-content h3 .btn .headerlink, .btn .rst-content h4 .headerlink, .rst-content h4 .btn .headerlink, .btn .rst-content h5 .headerlink, .rst-content h5 .btn .headerlink, .btn .rst-content h6 .headerlink, .rst-content h6 .btn .headerlink, .btn .rst-content dl dt .headerlink, .rst-content dl dt .btn .headerlink, .btn .icon, .nav .fa, .nav .wy-dropdown .caret, .wy-dropdown .nav .caret, .nav .wy-inline-validate.wy-inline-validate-success .wy-input-context, .wy-inline-validate.wy-inline-validate-success .nav .wy-input-context, .nav .wy-inline-validate.wy-inline-validate-danger .wy-input-context, .wy-inline-validate.wy-inline-validate-danger .nav .wy-input-context, .nav .wy-inline-validate.wy-inline-validate-warning .wy-input-context, .wy-inline-validate.wy-inline-validate-warning .nav .wy-input-context, .nav .wy-inline-validate.wy-inline-validate-info .wy-input-context, .wy-inline-validate.wy-inline-validate-info .nav .wy-input-context, .nav .wy-tag-input-group .wy-tag .wy-tag-remove, .wy-tag-input-group .wy-tag .nav .wy-tag-remove, .nav .rst-content .admonition-title, .rst-content .nav .admonition-title, .nav .rst-content h1 .headerlink, .rst-content h1 .nav .headerlink, .nav .rst-content h2 .headerlink, .rst-content h2 .nav .headerlink, .nav .rst-content h3 .headerlink, .rst-content h3 .nav .headerlink, .nav .rst-content h4 .headerlink, .rst-content h4 .nav .headerlink, .nav .rst-content h5 .headerlink, .rst-content h5 .nav .headerlink, .nav .rst-content h6 .headerlink, .rst-content h6 .nav .headerlink, .nav .rst-content dl dt .headerlink, .rst-content dl dt .nav .headerlink, .nav .icon { + display: inline; +} +.btn .fa.fa-large, .btn .wy-dropdown .fa-large.caret, .wy-dropdown .btn .fa-large.caret, .btn .wy-inline-validate.wy-inline-validate-success .fa-large.wy-input-context, .wy-inline-validate.wy-inline-validate-success .btn .fa-large.wy-input-context, .btn .wy-inline-validate.wy-inline-validate-danger .fa-large.wy-input-context, .wy-inline-validate.wy-inline-validate-danger .btn .fa-large.wy-input-context, .btn .wy-inline-validate.wy-inline-validate-warning .fa-large.wy-input-context, .wy-inline-validate.wy-inline-validate-warning .btn .fa-large.wy-input-context, .btn .wy-inline-validate.wy-inline-validate-info .fa-large.wy-input-context, .wy-inline-validate.wy-inline-validate-info .btn .fa-large.wy-input-context, .btn .wy-tag-input-group .wy-tag .fa-large.wy-tag-remove, .wy-tag-input-group .wy-tag .btn .fa-large.wy-tag-remove, .btn .rst-content .fa-large.admonition-title, .rst-content .btn .fa-large.admonition-title, .btn .rst-content h1 .fa-large.headerlink, .rst-content h1 .btn .fa-large.headerlink, .btn .rst-content h2 .fa-large.headerlink, .rst-content h2 .btn .fa-large.headerlink, .btn .rst-content h3 .fa-large.headerlink, .rst-content h3 .btn .fa-large.headerlink, .btn .rst-content h4 .fa-large.headerlink, .rst-content h4 .btn .fa-large.headerlink, .btn .rst-content h5 .fa-large.headerlink, .rst-content h5 .btn .fa-large.headerlink, .btn .rst-content h6 .fa-large.headerlink, .rst-content h6 .btn .fa-large.headerlink, .btn .rst-content dl dt .fa-large.headerlink, .rst-content dl dt .btn .fa-large.headerlink, .btn .fa-large.icon, .nav .fa.fa-large, .nav .wy-dropdown .fa-large.caret, .wy-dropdown .nav .fa-large.caret, .nav .wy-inline-validate.wy-inline-validate-success .fa-large.wy-input-context, .wy-inline-validate.wy-inline-validate-success .nav .fa-large.wy-input-context, .nav .wy-inline-validate.wy-inline-validate-danger .fa-large.wy-input-context, .wy-inline-validate.wy-inline-validate-danger .nav .fa-large.wy-input-context, .nav .wy-inline-validate.wy-inline-validate-warning .fa-large.wy-input-context, .wy-inline-validate.wy-inline-validate-warning .nav .fa-large.wy-input-context, .nav .wy-inline-validate.wy-inline-validate-info .fa-large.wy-input-context, .wy-inline-validate.wy-inline-validate-info .nav .fa-large.wy-input-context, .nav .wy-tag-input-group .wy-tag .fa-large.wy-tag-remove, .wy-tag-input-group .wy-tag .nav .fa-large.wy-tag-remove, .nav .rst-content .fa-large.admonition-title, .rst-content .nav .fa-large.admonition-title, .nav .rst-content h1 .fa-large.headerlink, .rst-content h1 .nav .fa-large.headerlink, .nav .rst-content h2 .fa-large.headerlink, .rst-content h2 .nav .fa-large.headerlink, .nav .rst-content h3 .fa-large.headerlink, .rst-content h3 .nav .fa-large.headerlink, .nav .rst-content h4 .fa-large.headerlink, .rst-content h4 .nav .fa-large.headerlink, .nav .rst-content h5 .fa-large.headerlink, .rst-content h5 .nav .fa-large.headerlink, .nav .rst-content h6 .fa-large.headerlink, .rst-content h6 .nav .fa-large.headerlink, .nav .rst-content dl dt .fa-large.headerlink, .rst-content dl dt .nav .fa-large.headerlink, .nav .fa-large.icon { + line-height: 0.9em; +} +.btn .fa.fa-spin, .btn .wy-dropdown .fa-spin.caret, .wy-dropdown .btn .fa-spin.caret, .btn .wy-inline-validate.wy-inline-validate-success .fa-spin.wy-input-context, .wy-inline-validate.wy-inline-validate-success .btn .fa-spin.wy-input-context, .btn .wy-inline-validate.wy-inline-validate-danger .fa-spin.wy-input-context, .wy-inline-validate.wy-inline-validate-danger .btn .fa-spin.wy-input-context, .btn .wy-inline-validate.wy-inline-validate-warning .fa-spin.wy-input-context, .wy-inline-validate.wy-inline-validate-warning .btn .fa-spin.wy-input-context, .btn .wy-inline-validate.wy-inline-validate-info .fa-spin.wy-input-context, .wy-inline-validate.wy-inline-validate-info .btn .fa-spin.wy-input-context, .btn .wy-tag-input-group .wy-tag .fa-spin.wy-tag-remove, .wy-tag-input-group .wy-tag .btn .fa-spin.wy-tag-remove, .btn .rst-content .fa-spin.admonition-title, .rst-content .btn .fa-spin.admonition-title, .btn .rst-content h1 .fa-spin.headerlink, .rst-content h1 .btn .fa-spin.headerlink, .btn .rst-content h2 .fa-spin.headerlink, .rst-content h2 .btn .fa-spin.headerlink, .btn .rst-content h3 .fa-spin.headerlink, .rst-content h3 .btn .fa-spin.headerlink, .btn .rst-content h4 .fa-spin.headerlink, .rst-content h4 .btn .fa-spin.headerlink, .btn .rst-content h5 .fa-spin.headerlink, .rst-content h5 .btn .fa-spin.headerlink, .btn .rst-content h6 .fa-spin.headerlink, .rst-content h6 .btn .fa-spin.headerlink, .btn .rst-content dl dt .fa-spin.headerlink, .rst-content dl dt .btn .fa-spin.headerlink, .btn .fa-spin.icon, .nav .fa.fa-spin, .nav .wy-dropdown .fa-spin.caret, .wy-dropdown .nav .fa-spin.caret, .nav .wy-inline-validate.wy-inline-validate-success .fa-spin.wy-input-context, .wy-inline-validate.wy-inline-validate-success .nav .fa-spin.wy-input-context, .nav .wy-inline-validate.wy-inline-validate-danger .fa-spin.wy-input-context, .wy-inline-validate.wy-inline-validate-danger .nav .fa-spin.wy-input-context, .nav .wy-inline-validate.wy-inline-validate-warning .fa-spin.wy-input-context, .wy-inline-validate.wy-inline-validate-warning .nav .fa-spin.wy-input-context, .nav .wy-inline-validate.wy-inline-validate-info .fa-spin.wy-input-context, .wy-inline-validate.wy-inline-validate-info .nav .fa-spin.wy-input-context, .nav .wy-tag-input-group .wy-tag .fa-spin.wy-tag-remove, .wy-tag-input-group .wy-tag .nav .fa-spin.wy-tag-remove, .nav .rst-content .fa-spin.admonition-title, .rst-content .nav .fa-spin.admonition-title, .nav .rst-content h1 .fa-spin.headerlink, .rst-content h1 .nav .fa-spin.headerlink, .nav .rst-content h2 .fa-spin.headerlink, .rst-content h2 .nav .fa-spin.headerlink, .nav .rst-content h3 .fa-spin.headerlink, .rst-content h3 .nav .fa-spin.headerlink, .nav .rst-content h4 .fa-spin.headerlink, .rst-content h4 .nav .fa-spin.headerlink, .nav .rst-content h5 .fa-spin.headerlink, .rst-content h5 .nav .fa-spin.headerlink, .nav .rst-content h6 .fa-spin.headerlink, .rst-content h6 .nav .fa-spin.headerlink, .nav .rst-content dl dt .fa-spin.headerlink, .rst-content dl dt .nav .fa-spin.headerlink, .nav .fa-spin.icon { + display: inline-block; +} + +.btn.fa:before, .wy-dropdown .btn.caret:before, .wy-inline-validate.wy-inline-validate-success .btn.wy-input-context:before, .wy-inline-validate.wy-inline-validate-danger .btn.wy-input-context:before, .wy-inline-validate.wy-inline-validate-warning .btn.wy-input-context:before, .wy-inline-validate.wy-inline-validate-info .btn.wy-input-context:before, .wy-tag-input-group .wy-tag .btn.wy-tag-remove:before, .rst-content .btn.admonition-title:before, .rst-content h1 .btn.headerlink:before, .rst-content h2 .btn.headerlink:before, .rst-content h3 .btn.headerlink:before, .rst-content h4 .btn.headerlink:before, .rst-content h5 .btn.headerlink:before, .rst-content h6 .btn.headerlink:before, .rst-content dl dt .btn.headerlink:before, .btn.icon:before { + opacity: 0.5; + -webkit-transition: opacity 0.05s ease-in; + -moz-transition: opacity 0.05s ease-in; + transition: opacity 0.05s ease-in; +} + +.btn.fa:hover:before, .wy-dropdown .btn.caret:hover:before, .wy-inline-validate.wy-inline-validate-success .btn.wy-input-context:hover:before, .wy-inline-validate.wy-inline-validate-danger .btn.wy-input-context:hover:before, .wy-inline-validate.wy-inline-validate-warning .btn.wy-input-context:hover:before, .wy-inline-validate.wy-inline-validate-info .btn.wy-input-context:hover:before, .wy-tag-input-group .wy-tag .btn.wy-tag-remove:hover:before, .rst-content .btn.admonition-title:hover:before, .rst-content h1 .btn.headerlink:hover:before, .rst-content h2 .btn.headerlink:hover:before, .rst-content h3 .btn.headerlink:hover:before, .rst-content h4 .btn.headerlink:hover:before, .rst-content h5 .btn.headerlink:hover:before, .rst-content h6 .btn.headerlink:hover:before, .rst-content dl dt .btn.headerlink:hover:before, .btn.icon:hover:before { + opacity: 1; +} + +.btn-mini .fa:before, .btn-mini .wy-dropdown .caret:before, .wy-dropdown .btn-mini .caret:before, .btn-mini .wy-inline-validate.wy-inline-validate-success .wy-input-context:before, .wy-inline-validate.wy-inline-validate-success .btn-mini .wy-input-context:before, .btn-mini .wy-inline-validate.wy-inline-validate-danger .wy-input-context:before, .wy-inline-validate.wy-inline-validate-danger .btn-mini .wy-input-context:before, .btn-mini .wy-inline-validate.wy-inline-validate-warning .wy-input-context:before, .wy-inline-validate.wy-inline-validate-warning .btn-mini .wy-input-context:before, .btn-mini .wy-inline-validate.wy-inline-validate-info .wy-input-context:before, .wy-inline-validate.wy-inline-validate-info .btn-mini .wy-input-context:before, .btn-mini .wy-tag-input-group .wy-tag .wy-tag-remove:before, .wy-tag-input-group .wy-tag .btn-mini .wy-tag-remove:before, .btn-mini .rst-content .admonition-title:before, .rst-content .btn-mini .admonition-title:before, .btn-mini .rst-content h1 .headerlink:before, .rst-content h1 .btn-mini .headerlink:before, .btn-mini .rst-content h2 .headerlink:before, .rst-content h2 .btn-mini .headerlink:before, .btn-mini .rst-content h3 .headerlink:before, .rst-content h3 .btn-mini .headerlink:before, .btn-mini .rst-content h4 .headerlink:before, .rst-content h4 .btn-mini .headerlink:before, .btn-mini .rst-content h5 .headerlink:before, .rst-content h5 .btn-mini .headerlink:before, .btn-mini .rst-content h6 .headerlink:before, .rst-content h6 .btn-mini .headerlink:before, .btn-mini .rst-content dl dt .headerlink:before, .rst-content dl dt .btn-mini .headerlink:before, .btn-mini .icon:before { + font-size: 14px; + vertical-align: -15%; +} + +.wy-alert, .rst-content .note, .rst-content .attention, .rst-content .caution, .rst-content .danger, .rst-content .error, .rst-content .hint, .rst-content .important, .rst-content .tip, .rst-content .warning, .rst-content .seealso { + padding: 12px; + line-height: 24px; + margin-bottom: 24px; +} + +.wy-alert-title, .rst-content .admonition-title { + color: white; + font-weight: bold; + display: block; + color: white; + background: transparent; + margin: -12px; + padding: 6px 12px; + margin-bottom: 12px; +} + +.wy-alert.wy-alert-danger, .rst-content .wy-alert-danger.note, .rst-content .wy-alert-danger.attention, .rst-content .wy-alert-danger.caution, .rst-content .danger, .rst-content .error, .rst-content .wy-alert-danger.hint, .rst-content .wy-alert-danger.important, .rst-content .wy-alert-danger.tip, .rst-content .wy-alert-danger.warning, .rst-content .wy-alert-danger.seealso { + background: #fdf3f2; +} +.wy-alert.wy-alert-danger .wy-alert-title, .rst-content .wy-alert-danger.note .wy-alert-title, .rst-content .wy-alert-danger.attention .wy-alert-title, .rst-content .wy-alert-danger.caution .wy-alert-title, .rst-content .danger .wy-alert-title, .rst-content .error .wy-alert-title, .rst-content .wy-alert-danger.hint .wy-alert-title, .rst-content .wy-alert-danger.important .wy-alert-title, .rst-content .wy-alert-danger.tip .wy-alert-title, .rst-content .wy-alert-danger.warning .wy-alert-title, .rst-content .wy-alert-danger.seealso .wy-alert-title, .wy-alert.wy-alert-danger .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-danger .admonition-title, .rst-content .wy-alert-danger.note .admonition-title, .rst-content .wy-alert-danger.attention .admonition-title, .rst-content .wy-alert-danger.caution .admonition-title, .rst-content .danger .admonition-title, .rst-content .error .admonition-title, .rst-content .wy-alert-danger.hint .admonition-title, .rst-content .wy-alert-danger.important .admonition-title, .rst-content .wy-alert-danger.tip .admonition-title, .rst-content .wy-alert-danger.warning .admonition-title, .rst-content .wy-alert-danger.seealso .admonition-title { + background: #f29f97; +} + +.wy-alert.wy-alert-warning, .rst-content .wy-alert-warning.note, .rst-content .attention, .rst-content .caution, .rst-content .wy-alert-warning.danger, .rst-content .wy-alert-warning.error, .rst-content .wy-alert-warning.hint, .rst-content .wy-alert-warning.important, .rst-content .wy-alert-warning.tip, .rst-content .warning, .rst-content .wy-alert-warning.seealso { + background: #ffedcc; +} +.wy-alert.wy-alert-warning .wy-alert-title, .rst-content .wy-alert-warning.note .wy-alert-title, .rst-content .attention .wy-alert-title, .rst-content .caution .wy-alert-title, .rst-content .wy-alert-warning.danger .wy-alert-title, .rst-content .wy-alert-warning.error .wy-alert-title, .rst-content .wy-alert-warning.hint .wy-alert-title, .rst-content .wy-alert-warning.important .wy-alert-title, .rst-content .wy-alert-warning.tip .wy-alert-title, .rst-content .warning .wy-alert-title, .rst-content .wy-alert-warning.seealso .wy-alert-title, .wy-alert.wy-alert-warning .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-warning .admonition-title, .rst-content .wy-alert-warning.note .admonition-title, .rst-content .attention .admonition-title, .rst-content .caution .admonition-title, .rst-content .wy-alert-warning.danger .admonition-title, .rst-content .wy-alert-warning.error .admonition-title, .rst-content .wy-alert-warning.hint .admonition-title, .rst-content .wy-alert-warning.important .admonition-title, .rst-content .wy-alert-warning.tip .admonition-title, .rst-content .warning .admonition-title, .rst-content .wy-alert-warning.seealso .admonition-title { + background: #f0b37e; +} + +.wy-alert.wy-alert-info, .rst-content .note, .rst-content .wy-alert-info.attention, .rst-content .wy-alert-info.caution, .rst-content .wy-alert-info.danger, .rst-content .wy-alert-info.error, .rst-content .wy-alert-info.hint, .rst-content .wy-alert-info.important, .rst-content .wy-alert-info.tip, .rst-content .wy-alert-info.warning, .rst-content .seealso { + background: #e7f2fa; +} +.wy-alert.wy-alert-info .wy-alert-title, .rst-content .note .wy-alert-title, .rst-content .wy-alert-info.attention .wy-alert-title, .rst-content .wy-alert-info.caution .wy-alert-title, .rst-content .wy-alert-info.danger .wy-alert-title, .rst-content .wy-alert-info.error .wy-alert-title, .rst-content .wy-alert-info.hint .wy-alert-title, .rst-content .wy-alert-info.important .wy-alert-title, .rst-content .wy-alert-info.tip .wy-alert-title, .rst-content .wy-alert-info.warning .wy-alert-title, .rst-content .seealso .wy-alert-title, .wy-alert.wy-alert-info .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-info .admonition-title, .rst-content .note .admonition-title, .rst-content .wy-alert-info.attention .admonition-title, .rst-content .wy-alert-info.caution .admonition-title, .rst-content .wy-alert-info.danger .admonition-title, .rst-content .wy-alert-info.error .admonition-title, .rst-content .wy-alert-info.hint .admonition-title, .rst-content .wy-alert-info.important .admonition-title, .rst-content .wy-alert-info.tip .admonition-title, .rst-content .wy-alert-info.warning .admonition-title, .rst-content .seealso .admonition-title { + background: #6ab0de; +} + +.wy-alert.wy-alert-success, .rst-content .wy-alert-success.note, .rst-content .wy-alert-success.attention, .rst-content .wy-alert-success.caution, .rst-content .wy-alert-success.danger, .rst-content .wy-alert-success.error, .rst-content .hint, .rst-content .important, .rst-content .tip, .rst-content .wy-alert-success.warning, .rst-content .wy-alert-success.seealso { + background: #dbfaf4; +} +.wy-alert.wy-alert-success .wy-alert-title, .rst-content .wy-alert-success.note .wy-alert-title, .rst-content .wy-alert-success.attention .wy-alert-title, .rst-content .wy-alert-success.caution .wy-alert-title, .rst-content .wy-alert-success.danger .wy-alert-title, .rst-content .wy-alert-success.error .wy-alert-title, .rst-content .hint .wy-alert-title, .rst-content .important .wy-alert-title, .rst-content .tip .wy-alert-title, .rst-content .wy-alert-success.warning .wy-alert-title, .rst-content .wy-alert-success.seealso .wy-alert-title, .wy-alert.wy-alert-success .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-success .admonition-title, .rst-content .wy-alert-success.note .admonition-title, .rst-content .wy-alert-success.attention .admonition-title, .rst-content .wy-alert-success.caution .admonition-title, .rst-content .wy-alert-success.danger .admonition-title, .rst-content .wy-alert-success.error .admonition-title, .rst-content .hint .admonition-title, .rst-content .important .admonition-title, .rst-content .tip .admonition-title, .rst-content .wy-alert-success.warning .admonition-title, .rst-content .wy-alert-success.seealso .admonition-title { + background: #1abc9c; +} + +.wy-alert.wy-alert-neutral, .rst-content .wy-alert-neutral.note, .rst-content .wy-alert-neutral.attention, .rst-content .wy-alert-neutral.caution, .rst-content .wy-alert-neutral.danger, .rst-content .wy-alert-neutral.error, .rst-content .wy-alert-neutral.hint, .rst-content .wy-alert-neutral.important, .rst-content .wy-alert-neutral.tip, .rst-content .wy-alert-neutral.warning, .rst-content .wy-alert-neutral.seealso { + background: #f3f6f6; +} +.wy-alert.wy-alert-neutral strong, .rst-content .wy-alert-neutral.note strong, .rst-content .wy-alert-neutral.attention strong, .rst-content .wy-alert-neutral.caution strong, .rst-content .wy-alert-neutral.danger strong, .rst-content .wy-alert-neutral.error strong, .rst-content .wy-alert-neutral.hint strong, .rst-content .wy-alert-neutral.important strong, .rst-content .wy-alert-neutral.tip strong, .rst-content .wy-alert-neutral.warning strong, .rst-content .wy-alert-neutral.seealso strong { + color: #404040; +} +.wy-alert.wy-alert-neutral a, .rst-content .wy-alert-neutral.note a, .rst-content .wy-alert-neutral.attention a, .rst-content .wy-alert-neutral.caution a, .rst-content .wy-alert-neutral.danger a, .rst-content .wy-alert-neutral.error a, .rst-content .wy-alert-neutral.hint a, .rst-content .wy-alert-neutral.important a, .rst-content .wy-alert-neutral.tip a, .rst-content .wy-alert-neutral.warning a, .rst-content .wy-alert-neutral.seealso a { + color: #2980b9; +} + +.wy-tray-container { + position: fixed; + top: -50px; + left: 0; + width: 100%; + -webkit-transition: top 0.2s ease-in; + -moz-transition: top 0.2s ease-in; + transition: top 0.2s ease-in; +} +.wy-tray-container.on { + top: 0; +} +.wy-tray-container li { + display: none; + width: 100%; + background: #343131; + padding: 12px 24px; + color: white; + margin-bottom: 6px; + text-align: center; + box-shadow: 0 5px 5px 0 rgba(0, 0, 0, 0.1), 0px -1px 2px -1px rgba(255, 255, 255, 0.5) inset; +} +.wy-tray-container li.wy-tray-item-success { + background: #27ae60; +} +.wy-tray-container li.wy-tray-item-info { + background: #2980b9; +} +.wy-tray-container li.wy-tray-item-warning { + background: #e67e22; +} +.wy-tray-container li.wy-tray-item-danger { + background: #e74c3c; +} + +.btn { + /* Structure */ + display: inline-block; + *display: inline; + /*IE 6/7 */ + zoom: 1; + line-height: normal; + white-space: nowrap; + vertical-align: baseline; + text-align: center; + cursor: pointer; + -webkit-user-drag: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + font-size: 100%; + padding: 6px 12px; + color: white; + border: 1px solid rgba(0, 0, 0, 0.1); + border-bottom: solid 3px rgba(0, 0, 0, 0.1); + background-color: #27ae60; + text-decoration: none; + font-weight: 500; + box-shadow: 0px 1px 2px -1px rgba(255, 255, 255, 0.5) inset; + -webkit-transition: all 0.1s linear; + -moz-transition: all 0.1s linear; + transition: all 0.1s linear; + outline-none: false; +} + +.btn-hover { + background: #2e8ece; + color: white; +} + +.btn:hover { + background: #2cc36b; + color: white; +} +.btn:focus { + background: #2cc36b; + color: white; + outline: 0; +} +.btn:active { + border-top: solid 3px rgba(0, 0, 0, 0.1); + border-bottom: solid 1px rgba(0, 0, 0, 0.1); + box-shadow: 0px 1px 2px -1px rgba(0, 0, 0, 0.5) inset; +} +.btn[disabled] { + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: alpha(opacity=40); + opacity: 0.4; + cursor: not-allowed; + box-shadow: none; +} +.btn:visited { + color: white; +} + +.btn-disabled { + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: alpha(opacity=40); + opacity: 0.4; + cursor: not-allowed; + box-shadow: none; +} +.btn-disabled:hover, .btn-disabled:focus, .btn-disabled:active { + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + filter: alpha(opacity=40); + opacity: 0.4; + cursor: not-allowed; + box-shadow: none; +} + +/* Firefox: Get rid of the inner focus border */ +.btn::-moz-focus-inner { + padding: 0; + border: 0; +} + +.btn-small { + font-size: 80%; +} + +.btn-info { + background-color: #2980b9 !important; +} +.btn-info:hover { + background-color: #2e8ece !important; +} + +.btn-neutral { + background-color: #f3f6f6 !important; + color: #404040 !important; +} +.btn-neutral:hover { + background-color: #e5ebeb !important; + color: #404040; +} +.btn-neutral:visited { + color: #404040 !important; +} + +.btn-success { + background-color: #27ae60 !important; +} +.btn-success:hover { + background-color: #229955 !important; +} + +.btn-danger { + background-color: #e74c3c !important; +} +.btn-danger:hover { + background-color: #ea6153 !important; +} + +.btn-warning { + background-color: #e67e22 !important; +} +.btn-warning:hover { + background-color: #e98b39 !important; +} + +.btn-invert { + background-color: #343131; +} +.btn-invert:hover { + background-color: #413d3d !important; +} + +.btn-link { + background-color: transparent !important; + color: #2980b9; + border-color: transparent; + box-shadow: none; +} +.btn-link:hover { + background-color: transparent !important; + color: #409ad5; + border-color: transparent; + box-shadow: none; +} +.btn-link:active { + background-color: transparent !important; + border-color: transparent; + border-top: solid 1px transparent; + border-bottom: solid 3px transparent; + box-shadow: none; +} +.btn-link:visited { + color: #9b59b6; +} + +.wy-btn-group .btn, .wy-control .btn { + vertical-align: middle; +} + +.wy-btn-group { + margin-bottom: 24px; + *zoom: 1; +} +.wy-btn-group:before, .wy-btn-group:after { + display: table; + content: ""; +} +.wy-btn-group:after { + clear: both; +} + +.wy-dropdown { + position: relative; + display: inline-block; +} + +.wy-dropdown-menu { + position: absolute; + top: 100%; + left: 0; + display: none; + float: left; + min-width: 100%; + background: #fcfcfc; + z-index: 100; + border: solid 1px #cfd7dd; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.1); + padding: 12px; +} +.wy-dropdown-menu > dd > a { + display: block; + clear: both; + color: #404040; + white-space: nowrap; + font-size: 90%; + padding: 0 12px; +} +.wy-dropdown-menu > dd > a:hover { + background: #2980b9; + color: white; +} +.wy-dropdown-menu > dd.divider { + border-top: solid 1px #cfd7dd; + margin: 6px 0; +} +.wy-dropdown-menu > dd.search { + padding-bottom: 12px; +} +.wy-dropdown-menu > dd.search input[type="search"] { + width: 100%; +} +.wy-dropdown-menu > dd.call-to-action { + background: #e3e3e3; + text-transform: uppercase; + font-weight: 500; + font-size: 80%; +} +.wy-dropdown-menu > dd.call-to-action:hover { + background: #e3e3e3; +} +.wy-dropdown-menu > dd.call-to-action .btn { + color: white; +} + +.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu { + background: #fcfcfc; + margin-top: 2px; +} +.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a { + padding: 6px 12px; +} +.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover { + background: #2980b9; + color: white; +} + +.wy-dropdown.wy-dropdown-left .wy-dropdown-menu { + right: 0; + text-align: right; +} + +.wy-dropdown-arrow:before { + content: " "; + border-bottom: 5px solid whitesmoke; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + position: absolute; + display: block; + top: -4px; + left: 50%; + margin-left: -3px; +} +.wy-dropdown-arrow.wy-dropdown-arrow-left:before { + left: 11px; +} + +.wy-form-stacked select { + display: block; +} + +.wy-form-aligned input, .wy-form-aligned textarea, .wy-form-aligned select, .wy-form-aligned .wy-help-inline, .wy-form-aligned label { + display: inline-block; + *display: inline; + *zoom: 1; + vertical-align: middle; +} + +.wy-form-aligned .wy-control-group > label { + display: inline-block; + vertical-align: middle; + width: 10em; + margin: 0.5em 1em 0 0; + float: left; +} +.wy-form-aligned .wy-control { + float: left; +} +.wy-form-aligned .wy-control label { + display: block; +} +.wy-form-aligned .wy-control select { + margin-top: 0.5em; +} + +fieldset { + border: 0; + margin: 0; + padding: 0; +} + +legend { + display: block; + width: 100%; + border: 0; + padding: 0; + white-space: normal; + margin-bottom: 24px; + font-size: 150%; + *margin-left: -7px; +} + +label { + display: block; + margin: 0 0 0.3125em 0; + color: #999999; + font-size: 90%; +} + +button, input, select, textarea { + font-size: 100%; + margin: 0; + vertical-align: baseline; + *vertical-align: middle; +} + +button, input { + line-height: normal; +} + +button { + -webkit-appearance: button; + cursor: pointer; + *overflow: visible; +} + +button::-moz-focus-inner, input::-moz-focus-inner { + border: 0; + padding: 0; +} + +button[disabled] { + cursor: default; +} + +input[type="button"], input[type="reset"], input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; + *overflow: visible; +} +input[type="text"], input[type="password"], input[type="email"], input[type="url"], input[type="date"], input[type="month"], input[type="time"], input[type="datetime"], input[type="datetime-local"], input[type="week"], input[type="number"], input[type="search"], input[type="tel"], input[type="color"] { + -webkit-appearance: none; + padding: 6px; + display: inline-block; + border: 1px solid #cccccc; + font-size: 80%; + font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; + box-shadow: inset 0 1px 3px #dddddd; + border-radius: 0; + -webkit-transition: border 0.3s linear; + -moz-transition: border 0.3s linear; + transition: border 0.3s linear; +} +input[type="datetime-local"] { + padding: 0.34375em 0.625em; +} +input[disabled] { + cursor: default; +} +input[type="checkbox"], input[type="radio"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0; + margin-right: 0.3125em; + *height: 13px; + *width: 13px; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +input[type="text"]:focus, input[type="password"]:focus, input[type="email"]:focus, input[type="url"]:focus, input[type="date"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="week"]:focus, input[type="number"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="color"]:focus { + outline: 0; + outline: thin dotted \9; + border-color: #333333; +} +input.no-focus:focus { + border-color: #cccccc !important; +} +input[type="file"]:focus, input[type="radio"]:focus, input[type="checkbox"]:focus { + outline: thin dotted #333333; + outline: 1px auto #129fea; +} +input[type="text"][disabled], input[type="password"][disabled], input[type="email"][disabled], input[type="url"][disabled], input[type="date"][disabled], input[type="month"][disabled], input[type="time"][disabled], input[type="datetime"][disabled], input[type="datetime-local"][disabled], input[type="week"][disabled], input[type="number"][disabled], input[type="search"][disabled], input[type="tel"][disabled], input[type="color"][disabled] { + cursor: not-allowed; + background-color: #f3f6f6; + color: #cad2d3; +} + +input:focus:invalid, textarea:focus:invalid, select:focus:invalid { + color: #e74c3c; + border: 1px solid #e74c3c; +} + +input:focus:invalid:focus, textarea:focus:invalid:focus, select:focus:invalid:focus { + border-color: #e74c3c; +} + +input[type="file"]:focus:invalid:focus, input[type="radio"]:focus:invalid:focus, input[type="checkbox"]:focus:invalid:focus { + outline-color: #e74c3c; +} + +input.wy-input-large { + padding: 12px; + font-size: 100%; +} + +textarea { + overflow: auto; + vertical-align: top; + width: 100%; +} + +select, textarea { + padding: 0.5em 0.625em; + display: inline-block; + border: 1px solid #cccccc; + font-size: 0.8em; + box-shadow: inset 0 1px 3px #dddddd; + -webkit-transition: border 0.3s linear; + -moz-transition: border 0.3s linear; + transition: border 0.3s linear; +} + +select { + border: 1px solid #cccccc; + background-color: white; +} +select[multiple] { + height: auto; +} + +select:focus, textarea:focus { + outline: 0; +} + +select[disabled], textarea[disabled], input[readonly], select[readonly], textarea[readonly] { + cursor: not-allowed; + background-color: white; + color: #cad2d3; + border-color: transparent; +} + +.wy-checkbox, .wy-radio { + margin: 0.5em 0; + color: #404040; + display: block; +} + +.wy-form-message-inline { + display: inline-block; + *display: inline; + *zoom: 1; + vertical-align: middle; +} + +.wy-input-prefix, .wy-input-suffix { + white-space: nowrap; +} +.wy-input-prefix .wy-input-context, .wy-input-suffix .wy-input-context { + padding: 6px; + display: inline-block; + font-size: 80%; + background-color: #f3f6f6; + border: solid 1px #cccccc; + color: #999999; +} + +.wy-input-suffix .wy-input-context { + border-left: 0; +} + +.wy-input-prefix .wy-input-context { + border-right: 0; +} + +.wy-inline-validate { + white-space: nowrap; +} +.wy-inline-validate .wy-input-context { + padding: 0.5em 0.625em; + display: inline-block; + font-size: 80%; +} + +.wy-inline-validate.wy-inline-validate-success .wy-input-context { + color: #27ae60; +} + +.wy-inline-validate.wy-inline-validate-danger .wy-input-context { + color: #e74c3c; +} + +.wy-inline-validate.wy-inline-validate-warning .wy-input-context { + color: #e67e22; +} + +.wy-inline-validate.wy-inline-validate-info .wy-input-context { + color: #2980b9; +} + +.wy-control-group { + margin-bottom: 24px; + *zoom: 1; + max-width: 68em; + margin-left: auto; + margin-right: auto; + *zoom: 1; +} +.wy-control-group:before, .wy-control-group:after { + display: table; + content: ""; +} +.wy-control-group:after { + clear: both; +} +.wy-control-group:before, .wy-control-group:after { + display: table; + content: ""; +} +.wy-control-group:after { + clear: both; +} + +.wy-control-group.wy-control-group-error .wy-form-message, .wy-control-group.wy-control-group-error > label { + color: #e74c3c; +} +.wy-control-group.wy-control-group-error input[type="text"], .wy-control-group.wy-control-group-error input[type="password"], .wy-control-group.wy-control-group-error input[type="email"], .wy-control-group.wy-control-group-error input[type="url"], .wy-control-group.wy-control-group-error input[type="date"], .wy-control-group.wy-control-group-error input[type="month"], .wy-control-group.wy-control-group-error input[type="time"], .wy-control-group.wy-control-group-error input[type="datetime"], .wy-control-group.wy-control-group-error input[type="datetime-local"], .wy-control-group.wy-control-group-error input[type="week"], .wy-control-group.wy-control-group-error input[type="number"], .wy-control-group.wy-control-group-error input[type="search"], .wy-control-group.wy-control-group-error input[type="tel"], .wy-control-group.wy-control-group-error input[type="color"] { + border: solid 1px #e74c3c; +} +.wy-control-group.wy-control-group-error textarea { + border: solid 1px #e74c3c; +} + +.wy-control-group.wy-control-group-required > label:after { + content: " *"; + color: #e74c3c; +} + +.wy-control-group .wy-form-full, .wy-control-group .wy-form-halves, .wy-control-group .wy-form-thirds { + padding-bottom: 12px; +} +.wy-control-group .wy-form-full select, .wy-control-group .wy-form-halves select, .wy-control-group .wy-form-thirds select { + width: 100%; +} +.wy-control-group .wy-form-full input[type="text"], .wy-control-group .wy-form-full input[type="password"], .wy-control-group .wy-form-full input[type="email"], .wy-control-group .wy-form-full input[type="url"], .wy-control-group .wy-form-full input[type="date"], .wy-control-group .wy-form-full input[type="month"], .wy-control-group .wy-form-full input[type="time"], .wy-control-group .wy-form-full input[type="datetime"], .wy-control-group .wy-form-full input[type="datetime-local"], .wy-control-group .wy-form-full input[type="week"], .wy-control-group .wy-form-full input[type="number"], .wy-control-group .wy-form-full input[type="search"], .wy-control-group .wy-form-full input[type="tel"], .wy-control-group .wy-form-full input[type="color"], .wy-control-group .wy-form-halves input[type="text"], .wy-control-group .wy-form-halves input[type="password"], .wy-control-group .wy-form-halves input[type="email"], .wy-control-group .wy-form-halves input[type="url"], .wy-control-group .wy-form-halves input[type="date"], .wy-control-group .wy-form-halves input[type="month"], .wy-control-group .wy-form-halves input[type="time"], .wy-control-group .wy-form-halves input[type="datetime"], .wy-control-group .wy-form-halves input[type="datetime-local"], .wy-control-group .wy-form-halves input[type="week"], .wy-control-group .wy-form-halves input[type="number"], .wy-control-group .wy-form-halves input[type="search"], .wy-control-group .wy-form-halves input[type="tel"], .wy-control-group .wy-form-halves input[type="color"], .wy-control-group .wy-form-thirds input[type="text"], .wy-control-group .wy-form-thirds input[type="password"], .wy-control-group .wy-form-thirds input[type="email"], .wy-control-group .wy-form-thirds input[type="url"], .wy-control-group .wy-form-thirds input[type="date"], .wy-control-group .wy-form-thirds input[type="month"], .wy-control-group .wy-form-thirds input[type="time"], .wy-control-group .wy-form-thirds input[type="datetime"], .wy-control-group .wy-form-thirds input[type="datetime-local"], .wy-control-group .wy-form-thirds input[type="week"], .wy-control-group .wy-form-thirds input[type="number"], .wy-control-group .wy-form-thirds input[type="search"], .wy-control-group .wy-form-thirds input[type="tel"], .wy-control-group .wy-form-thirds input[type="color"] { + width: 100%; +} + +.wy-control-group .wy-form-full { + display: block; + float: left; + margin-right: 2.35765%; + width: 100%; + margin-right: 0; +} +.wy-control-group .wy-form-full:last-child { + margin-right: 0; +} + +.wy-control-group .wy-form-halves { + display: block; + float: left; + margin-right: 2.35765%; + width: 48.82117%; +} +.wy-control-group .wy-form-halves:last-child { + margin-right: 0; +} +.wy-control-group .wy-form-halves:nth-of-type(2n) { + margin-right: 0; +} +.wy-control-group .wy-form-halves:nth-of-type(2n+1) { + clear: left; +} + +.wy-control-group .wy-form-thirds { + display: block; + float: left; + margin-right: 2.35765%; + width: 31.76157%; +} +.wy-control-group .wy-form-thirds:last-child { + margin-right: 0; +} +.wy-control-group .wy-form-thirds:nth-of-type(3n) { + margin-right: 0; +} +.wy-control-group .wy-form-thirds:nth-of-type(3n+1) { + clear: left; +} + +.wy-control-group.wy-control-group-no-input .wy-control { + margin: 0.5em 0 0 0; + font-size: 90%; +} + +.wy-control-group.fluid-input input[type="text"], .wy-control-group.fluid-input input[type="password"], .wy-control-group.fluid-input input[type="email"], .wy-control-group.fluid-input input[type="url"], .wy-control-group.fluid-input input[type="date"], .wy-control-group.fluid-input input[type="month"], .wy-control-group.fluid-input input[type="time"], .wy-control-group.fluid-input input[type="datetime"], .wy-control-group.fluid-input input[type="datetime-local"], .wy-control-group.fluid-input input[type="week"], .wy-control-group.fluid-input input[type="number"], .wy-control-group.fluid-input input[type="search"], .wy-control-group.fluid-input input[type="tel"], .wy-control-group.fluid-input input[type="color"] { + width: 100%; +} + +.wy-form-message-inline { + display: inline-block; + padding-left: 0.3em; + color: #666666; + vertical-align: middle; + font-size: 90%; +} + +.wy-form-message { + display: block; + color: #cccccc; + font-size: 70%; + margin-top: 0.3125em; + font-style: italic; +} + +.wy-tag-input-group { + padding: 4px 4px 0px 4px; + display: inline-block; + border: 1px solid #cccccc; + font-size: 80%; + font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; + box-shadow: inset 0 1px 3px #dddddd; + background: white; + -webkit-transition: border 0.3s linear; + -moz-transition: border 0.3s linear; + transition: border 0.3s linear; +} +.wy-tag-input-group .wy-tag { + display: inline-block; + background-color: rgba(0, 0, 0, 0.1); + padding: 0.5em 0.625em; + border-radius: 2px; + position: relative; + margin-bottom: 4px; +} +.wy-tag-input-group .wy-tag .wy-tag-remove { + color: #cccccc; + margin-left: 5px; +} +.wy-tag-input-group .wy-tag .wy-tag-remove:hover { + color: #e74c3c; +} +.wy-tag-input-group label { + margin-left: 5px; + display: inline-block; + margin-bottom: 0; +} +.wy-tag-input-group input { + border: none; + font-size: 100%; + margin-bottom: 4px; + box-shadow: none; +} + +.wy-form-upload { + border: solid 1px #cccccc; + border-bottom: solid 3px #cccccc; + background-color: #f3f6f6; + padding: 24px; + display: inline-block; + text-align: center; + cursor: pointer; + color: #404040; + -webkit-transition: border-color 0.1s ease-in; + -moz-transition: border-color 0.1s ease-in; + transition: border-color 0.1s ease-in; + *zoom: 1; +} +.wy-form-upload:before, .wy-form-upload:after { + display: table; + content: ""; +} +.wy-form-upload:after { + clear: both; +} +@media screen and (max-width: 480px) { + .wy-form-upload { + width: 100%; + } +} +.wy-form-upload .image-drop { + display: none; +} +.wy-form-upload .image-desktop { + display: none; +} +.wy-form-upload .image-loading { + display: none; +} +.wy-form-upload .wy-form-upload-icon { + display: block; + font-size: 32px; + color: #b3b3b3; +} +.wy-form-upload .image-drop .wy-form-upload-icon { + color: #27ae60; +} +.wy-form-upload p { + font-size: 90%; +} +.wy-form-upload .wy-form-upload-image { + float: left; + margin-right: 24px; +} +@media screen and (max-width: 480px) { + .wy-form-upload .wy-form-upload-image { + width: 100%; + margin-bottom: 24px; + } +} +.wy-form-upload img { + max-width: 125px; + max-height: 125px; + opacity: 0.9; + -webkit-transition: opacity 0.1s ease-in; + -moz-transition: opacity 0.1s ease-in; + transition: opacity 0.1s ease-in; +} +.wy-form-upload .wy-form-upload-content { + float: left; +} +@media screen and (max-width: 480px) { + .wy-form-upload .wy-form-upload-content { + width: 100%; + } +} + +.wy-form-upload:hover { + border-color: #b3b3b3; + color: #404040; +} +.wy-form-upload:hover .image-desktop { + display: block; +} +.wy-form-upload:hover .image-drag { + display: none; +} +.wy-form-upload:hover img { + opacity: 1; +} + +.wy-form-upload:active { + border-top: solid 3px #cccccc; + border-bottom: solid 1px #cccccc; +} + +.wy-form-upload.wy-form-upload-big { + width: 100%; + text-align: center; + padding: 72px; +} +.wy-form-upload.wy-form-upload-big .wy-form-upload-content { + float: none; +} + +.wy-form-upload.wy-form-upload-file p { + margin-bottom: 0; +} +.wy-form-upload.wy-form-upload-file .wy-form-upload-icon { + display: inline-block; + font-size: inherit; +} + +.wy-form-upload.wy-form-upload-drop { + background-color: #ddf7e8; +} +.wy-form-upload.wy-form-upload-drop .image-drop { + display: block; +} +.wy-form-upload.wy-form-upload-drop .image-desktop { + display: none; +} +.wy-form-upload.wy-form-upload-drop .image-drag { + display: none; +} + +.wy-form-upload.wy-form-upload-loading .image-drag { + display: none; +} +.wy-form-upload.wy-form-upload-loading .image-desktop { + display: none; +} +.wy-form-upload.wy-form-upload-loading .image-loading { + display: block; +} +.wy-form-upload.wy-form-upload-loading .wy-input-prefix { + display: none; +} +.wy-form-upload.wy-form-upload-loading p { + margin-bottom: 0; +} + +.rotate-90 { + -webkit-transform: rotate(90deg); + -moz-transform: rotate(90deg); + -ms-transform: rotate(90deg); + -o-transform: rotate(90deg); + transform: rotate(90deg); +} + +.rotate-180 { + -webkit-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -o-transform: rotate(180deg); + transform: rotate(180deg); +} + +.rotate-270 { + -webkit-transform: rotate(270deg); + -moz-transform: rotate(270deg); + -ms-transform: rotate(270deg); + -o-transform: rotate(270deg); + transform: rotate(270deg); +} + +.mirror { + -webkit-transform: scaleX(-1); + -moz-transform: scaleX(-1); + -ms-transform: scaleX(-1); + -o-transform: scaleX(-1); + transform: scaleX(-1); +} +.mirror.rotate-90 { + -webkit-transform: scaleX(-1) rotate(90deg); + -moz-transform: scaleX(-1) rotate(90deg); + -ms-transform: scaleX(-1) rotate(90deg); + -o-transform: scaleX(-1) rotate(90deg); + transform: scaleX(-1) rotate(90deg); +} +.mirror.rotate-180 { + -webkit-transform: scaleX(-1) rotate(180deg); + -moz-transform: scaleX(-1) rotate(180deg); + -ms-transform: scaleX(-1) rotate(180deg); + -o-transform: scaleX(-1) rotate(180deg); + transform: scaleX(-1) rotate(180deg); +} +.mirror.rotate-270 { + -webkit-transform: scaleX(-1) rotate(270deg); + -moz-transform: scaleX(-1) rotate(270deg); + -ms-transform: scaleX(-1) rotate(270deg); + -o-transform: scaleX(-1) rotate(270deg); + transform: scaleX(-1) rotate(270deg); +} + +.wy-form-gallery-manage { + margin-left: -12px; + margin-right: -12px; +} +.wy-form-gallery-manage li { + float: left; + padding: 12px; + width: 20%; + cursor: pointer; +} +@media screen and (max-width: 768px) { + .wy-form-gallery-manage li { + width: 25%; + } +} +@media screen and (max-width: 480px) { + .wy-form-gallery-manage li { + width: 50%; + } +} +.wy-form-gallery-manage li:active { + cursor: move; +} +.wy-form-gallery-manage li > a { + padding: 12px; + background-color: white; + border: solid 1px #e1e4e5; + border-bottom: solid 3px #e1e4e5; + display: inline-block; + -webkit-transition: all 0.1s ease-in; + -moz-transition: all 0.1s ease-in; + transition: all 0.1s ease-in; +} +.wy-form-gallery-manage li > a:active { + border: solid 1px #cccccc; + border-top: solid 3px #cccccc; +} +.wy-form-gallery-manage img { + width: 100%; + -webkit-transition: all 0.05s ease-in; + -moz-transition: all 0.05s ease-in; + transition: all 0.05s ease-in; +} + +li.wy-form-gallery-edit { + position: relative; + color: white; + padding: 24px; + width: 100%; + display: block; + background-color: #343131; + border-radius: 4px; +} +li.wy-form-gallery-edit .arrow { + position: absolute; + display: block; + top: -50px; + left: 50%; + margin-left: -25px; + z-index: 500; + height: 0; + width: 0; + border-color: transparent; + border-style: solid; + border-width: 25px; + border-bottom-color: #343131; +} + +@media only screen and (max-width: 480px) { + .wy-form button[type="submit"] { + margin: 0.7em 0 0; + } + .wy-form input[type="text"], .wy-form input[type="password"], .wy-form input[type="email"], .wy-form input[type="url"], .wy-form input[type="date"], .wy-form input[type="month"], .wy-form input[type="time"], .wy-form input[type="datetime"], .wy-form input[type="datetime-local"], .wy-form input[type="week"], .wy-form input[type="number"], .wy-form input[type="search"], .wy-form input[type="tel"], .wy-form input[type="color"] { + margin-bottom: 0.3em; + display: block; + } + .wy-form label { + margin-bottom: 0.3em; + display: block; + } + + .wy-form input[type="password"], .wy-form input[type="email"], .wy-form input[type="url"], .wy-form input[type="date"], .wy-form input[type="month"], .wy-form input[type="time"], .wy-form input[type="datetime"], .wy-form input[type="datetime-local"], .wy-form input[type="week"], .wy-form input[type="number"], .wy-form input[type="search"], .wy-form input[type="tel"], .wy-form input[type="color"] { + margin-bottom: 0; + } + + .wy-form-aligned .wy-control-group label { + margin-bottom: 0.3em; + text-align: left; + display: block; + width: 100%; + } + .wy-form-aligned .wy-controls { + margin: 1.5em 0 0 0; + } + + /* NOTE: wy-help-inline is deprecated. Use .wy-form-message-inline instead. */ + .wy-form .wy-help-inline, .wy-form-message-inline, .wy-form-message { + display: block; + font-size: 80%; + /* Increased bottom padding to make it group with its related input element. */ + padding: 0.2em 0 0.8em; + } +} +@media screen and (max-width: 768px) { + .tablet-hide { + display: none; + } +} + +@media screen and (max-width: 480px) { + .mobile-hide { + display: none; + } +} + +.float-left { + float: left; +} + +.float-right { + float: right; +} + +.full-width { + width: 100%; +} + +.wy-grid-one-col { + *zoom: 1; + max-width: 68em; + margin-left: auto; + margin-right: auto; + max-width: 1066px; + margin-top: 1.618em; +} +.wy-grid-one-col:before, .wy-grid-one-col:after { + display: table; + content: ""; +} +.wy-grid-one-col:after { + clear: both; +} +.wy-grid-one-col section { + display: block; + float: left; + margin-right: 2.35765%; + width: 100%; + background: #fcfcfc; + padding: 1.618em; + margin-right: 0; +} +.wy-grid-one-col section:last-child { + margin-right: 0; +} + +.wy-grid-index-card { + *zoom: 1; + max-width: 68em; + margin-left: auto; + margin-right: auto; + max-width: 460px; + margin-top: 1.618em; + background: #fcfcfc; + padding: 1.618em; +} +.wy-grid-index-card:before, .wy-grid-index-card:after { + display: table; + content: ""; +} +.wy-grid-index-card:after { + clear: both; +} +.wy-grid-index-card header, .wy-grid-index-card section, .wy-grid-index-card aside { + display: block; + float: left; + margin-right: 2.35765%; + width: 100%; +} +.wy-grid-index-card header:last-child, .wy-grid-index-card section:last-child, .wy-grid-index-card aside:last-child { + margin-right: 0; +} +.wy-grid-index-card.twocol { + max-width: 768px; +} +.wy-grid-index-card.twocol section { + display: block; + float: left; + margin-right: 2.35765%; + width: 48.82117%; +} +.wy-grid-index-card.twocol section:last-child { + margin-right: 0; +} +.wy-grid-index-card.twocol aside { + display: block; + float: left; + margin-right: 2.35765%; + width: 48.82117%; +} +.wy-grid-index-card.twocol aside:last-child { + margin-right: 0; +} + +.wy-grid-search-filter { + *zoom: 1; + max-width: 68em; + margin-left: auto; + margin-right: auto; + margin-bottom: 24px; +} +.wy-grid-search-filter:before, .wy-grid-search-filter:after { + display: table; + content: ""; +} +.wy-grid-search-filter:after { + clear: both; +} +.wy-grid-search-filter .wy-grid-search-filter-input { + display: block; + float: left; + margin-right: 2.35765%; + width: 74.41059%; +} +.wy-grid-search-filter .wy-grid-search-filter-input:last-child { + margin-right: 0; +} +.wy-grid-search-filter .wy-grid-search-filter-btn { + display: block; + float: left; + margin-right: 2.35765%; + width: 23.23176%; +} +.wy-grid-search-filter .wy-grid-search-filter-btn:last-child { + margin-right: 0; +} + +.wy-table, .rst-content table.docutils, .rst-content table.field-list { + /* Remove spacing between table cells (from Normalize.css) */ + border-collapse: collapse; + border-spacing: 0; + empty-cells: show; + margin-bottom: 24px; +} +.wy-table caption, .rst-content table.docutils caption, .rst-content table.field-list caption { + color: black; + font: italic 85%/1 arial, sans-serif; + padding: 1em 0; + text-align: center; +} +.wy-table td, .rst-content table.docutils td, .rst-content table.field-list td, .wy-table th, .rst-content table.docutils th, .rst-content table.field-list th { + font-size: 90%; + margin: 0; + overflow: visible; + padding: 8px 16px; +} +.wy-table td:first-child, .rst-content table.docutils td:first-child, .rst-content table.field-list td:first-child, .wy-table th:first-child, .rst-content table.docutils th:first-child, .rst-content table.field-list th:first-child { + border-left-width: 0; +} +.wy-table thead, .rst-content table.docutils thead, .rst-content table.field-list thead { + color: black; + text-align: left; + vertical-align: bottom; + white-space: nowrap; +} +.wy-table thead th, .rst-content table.docutils thead th, .rst-content table.field-list thead th { + font-weight: bold; + border-bottom: solid 2px #e1e4e5; +} +.wy-table td, .rst-content table.docutils td, .rst-content table.field-list td { + background-color: transparent; + vertical-align: middle; +} + +.wy-table td p, .rst-content table.docutils td p, .rst-content table.field-list td p { + line-height: 18px; + margin-bottom: 0; +} + +.wy-table .wy-table-cell-min, .rst-content table.docutils .wy-table-cell-min, .rst-content table.field-list .wy-table-cell-min { + width: 1%; + padding-right: 0; +} +.wy-table .wy-table-cell-min input[type=checkbox], .rst-content table.docutils .wy-table-cell-min input[type=checkbox], .rst-content table.field-list .wy-table-cell-min input[type=checkbox], .wy-table .wy-table-cell-min input[type=checkbox], .rst-content table.docutils .wy-table-cell-min input[type=checkbox], .rst-content table.field-list .wy-table-cell-min input[type=checkbox] { + margin: 0; +} + +.wy-table-secondary { + color: gray; + font-size: 90%; +} + +.wy-table-tertiary { + color: gray; + font-size: 80%; +} + +/*striping: + * even - #fff (white) + * odd - #f2f2f2 (light gray) */ +.wy-table-odd td, .wy-table-striped tr:nth-child(2n-1) td, .rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td { + background-color: #f3f6f6; +} + +.wy-table-backed { + background-color: #f3f6f6; +} + +/* nth-child selector for modern browsers */ +/* BORDERED TABLES */ +.wy-table-bordered-all, .rst-content table.docutils { + border: 1px solid #e1e4e5; +} +.wy-table-bordered-all td, .rst-content table.docutils td { + border-bottom: 1px solid #e1e4e5; + border-left: 1px solid #e1e4e5; +} +.wy-table-bordered-all tbody > tr:last-child td, .rst-content table.docutils tbody > tr:last-child td { + border-bottom-width: 0; +} + +.wy-table-bordered { + border: 1px solid #e1e4e5; +} + +.wy-table-bordered-rows td { + border-bottom: 1px solid #e1e4e5; +} +.wy-table-bordered-rows tbody > tr:last-child td { + border-bottom-width: 0; +} + +.wy-table-horizontal tbody > tr:last-child td { + border-bottom-width: 0; +} +.wy-table-horizontal td, .wy-table-horizontal th { + border-width: 0 0 1px 0; + border-bottom: 1px solid #e1e4e5; +} +.wy-table-horizontal tbody > tr:last-child td { + border-bottom-width: 0; +} + +/* RESPONSIVE TABLES */ +.wy-table-responsive { + margin-bottom: 24px; + max-width: 100%; + overflow: auto; +} +.wy-table-responsive table { + margin-bottom: 0 !important; +} +.wy-table-responsive table td, .wy-table-responsive table th { + white-space: nowrap; +} + +html { + height: 100%; + overflow-x: hidden; +} + +body { + font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; + font-weight: normal; + color: #404040; + min-height: 100%; + overflow-x: hidden; + background: #edf0f2; +} + +a { + color: #2980b9; + text-decoration: none; +} +a:hover { + color: #3091d1; +} +a:visited { + color: #9b59b6; +} + +.link-danger { + color: #e74c3c; +} +.link-danger:hover { + color: #d62c1a; +} + +.text-left { + text-align: left; +} + +.text-center { + text-align: center; +} + +.text-right { + text-align: right; +} + +h1, h2, h3, h4, h5, h6, legend { + margin-top: 0; + font-weight: 700; + font-family: "Roboto Slab", "ff-tisa-web-pro", "Georgia", Arial, sans-serif; +} + +p { + line-height: 24px; + margin: 0; + font-size: 16px; + margin-bottom: 24px; +} + +h1 { + font-size: 175%; +} + +h2 { + font-size: 150%; +} + +h3 { + font-size: 125%; +} + +h4 { + font-size: 115%; +} + +h5 { + font-size: 110%; +} + +h6 { + font-size: 100%; +} + +small { + font-size: 80%; +} + +code, .rst-content tt { + white-space: nowrap; + max-width: 100%; + background: white; + border: solid 1px #e1e4e5; + font-size: 75%; + padding: 0 5px; + font-family: "Incosolata", "Consolata", "Monaco", monospace; + color: #e74c3c; + overflow-x: auto; +} +code.code-large, .rst-content tt.code-large { + font-size: 90%; +} + +.full-width { + width: 100%; +} + +.wy-plain-list-disc, .rst-content .section ul, .rst-content .toctree-wrapper ul { + list-style: disc; + line-height: 24px; + margin-bottom: 24px; +} + +.wy-plain-list-disc li, .rst-content .section ul li, .rst-content .toctree-wrapper ul li { + list-style: disc; + margin-left: 24px; +} +.wy-plain-list-disc li ul, .rst-content .section ul li ul, .rst-content .toctree-wrapper ul li ul { + margin-bottom: 0; +} +.wy-plain-list-disc li li, .rst-content .section ul li li, .rst-content .toctree-wrapper ul li li { + list-style: circle; +} +.wy-plain-list-disc li li li, .rst-content .section ul li li li, .rst-content .toctree-wrapper ul li li li { + list-style: square; +} + +.wy-plain-list-decimal, .rst-content .section ol, .rst-content ol.arabic { + list-style: decimal; + line-height: 24px; + margin-bottom: 24px; +} + +.wy-plain-list-decimal li, .rst-content .section ol li, .rst-content ol.arabic li { + list-style: decimal; + margin-left: 24px; +} + +.wy-type-large { + font-size: 120%; +} + +.wy-type-normal { + font-size: 100%; +} + +.wy-type-small { + font-size: 100%; +} + +.wy-type-strike { + text-decoration: line-through; +} + +.wy-text-warning { + color: #e67e22 !important; +} + +a.wy-text-warning:hover { + color: #eb9950 !important; +} + +.wy-text-info { + color: #2980b9 !important; +} + +a.wy-text-info:hover { + color: #409ad5 !important; +} + +.wy-text-success { + color: #27ae60 !important; +} + +a.wy-text-success:hover { + color: #36d278 !important; +} + +.wy-text-danger { + color: #e74c3c !important; +} + +a.wy-text-danger:hover { + color: #ed7669 !important; +} + +.wy-text-neutral { + color: #404040 !important; +} + +a.wy-text-neutral:hover { + color: #595959 !important; +} + +.codeblock-example { + border: 1px solid #e1e4e5; + border-bottom: none; + padding: 24px; + padding-top: 48px; + font-weight: 500; + background: white; + position: relative; +} +.codeblock-example:after { + content: "Example"; + position: absolute; + top: 0px; + left: 0px; + background: #9b59b6; + color: white; + padding: 6px 12px; +} +.codeblock-example.prettyprint-example-only { + border: 1px solid #e1e4e5; + margin-bottom: 24px; +} + +.codeblock, pre.literal-block, .rst-content .literal-block, div[class^='highlight'] { + border: 1px solid #e1e4e5; + padding: 0px; + overflow-x: auto; + background: white; + margin: 1px 0 24px 0; +} +.codeblock div[class^='highlight'], pre.literal-block div[class^='highlight'], .rst-content .literal-block div[class^='highlight'], div[class^='highlight'] div[class^='highlight'] { + border: none; + background: none; + margin: 0; +} + +div[class^='highlight'] td.code { + width: 100%; +} + +.linenodiv pre { + border-right: solid 1px #e6e9ea; + margin: 0; + padding: 12px 12px; + font-family: "Incosolata", "Consolata", "Monaco", monospace; + font-size: 12px; + line-height: 1.5; + color: #d9d9d9; +} + +div[class^='highlight'] pre { + white-space: pre; + margin: 0; + padding: 12px 12px; + font-family: "Incosolata", "Consolata", "Monaco", monospace; + font-size: 12px; + line-height: 1.5; + display: block; + overflow: auto; + color: #404040; +} + +@media print { + .codeblock, pre.literal-block, .rst-content .literal-block, div[class^='highlight'], div[class^='highlight'] pre { + white-space: pre-wrap; + } +} +.hll { + background-color: #ffffcc; + margin: 0 -12px; + padding: 0 12px; + display: block; +} + +.c { + color: #999988; + font-style: italic; +} + +.err { + color: #a61717; + background-color: #e3d2d2; +} + +.k { + font-weight: bold; +} + +.o { + font-weight: bold; +} + +.cm { + color: #999988; + font-style: italic; +} + +.cp { + color: #999999; + font-weight: bold; +} + +.c1 { + color: #999988; + font-style: italic; +} + +.cs { + color: #999999; + font-weight: bold; + font-style: italic; +} + +.gd { + color: black; + background-color: #ffdddd; +} + +.gd .x { + color: black; + background-color: #ffaaaa; +} + +.ge { + font-style: italic; +} + +.gr { + color: #aa0000; +} + +.gh { + color: #999999; +} + +.gi { + color: black; + background-color: #ddffdd; +} + +.gi .x { + color: black; + background-color: #aaffaa; +} + +.go { + color: #888888; +} + +.gp { + color: #555555; +} + +.gs { + font-weight: bold; +} + +.gu { + color: purple; + font-weight: bold; +} + +.gt { + color: #aa0000; +} + +.kc { + font-weight: bold; +} + +.kd { + font-weight: bold; +} + +.kn { + font-weight: bold; +} + +.kp { + font-weight: bold; +} + +.kr { + font-weight: bold; +} + +.kt { + color: #445588; + font-weight: bold; +} + +.m { + color: #009999; +} + +.s { + color: #dd1144; +} + +.n { + color: #333333; +} + +.na { + color: teal; +} + +.nb { + color: #0086b3; +} + +.nc { + color: #445588; + font-weight: bold; +} + +.no { + color: teal; +} + +.ni { + color: purple; +} + +.ne { + color: #990000; + font-weight: bold; +} + +.nf { + color: #990000; + font-weight: bold; +} + +.nn { + color: #555555; +} + +.nt { + color: navy; +} + +.nv { + color: teal; +} + +.ow { + font-weight: bold; +} + +.w { + color: #bbbbbb; +} + +.mf { + color: #009999; +} + +.mh { + color: #009999; +} + +.mi { + color: #009999; +} + +.mo { + color: #009999; +} + +.sb { + color: #dd1144; +} + +.sc { + color: #dd1144; +} + +.sd { + color: #dd1144; +} + +.s2 { + color: #dd1144; +} + +.se { + color: #dd1144; +} + +.sh { + color: #dd1144; +} + +.si { + color: #dd1144; +} + +.sx { + color: #dd1144; +} + +.sr { + color: #009926; +} + +.s1 { + color: #dd1144; +} + +.ss { + color: #990073; +} + +.bp { + color: #999999; +} + +.vc { + color: teal; +} + +.vg { + color: teal; +} + +.vi { + color: teal; +} + +.il { + color: #009999; +} + +.gc { + color: #999999; + background-color: #eaf2f5; +} + +.wy-breadcrumbs li { + display: inline-block; +} +.wy-breadcrumbs li.wy-breadcrumbs-aside { + float: right; +} +.wy-breadcrumbs li a { + display: inline-block; + padding: 5px; +} +.wy-breadcrumbs li a:first-child { + padding-left: 0; +} + +.wy-breadcrumbs-extra { + margin-bottom: 0; + color: #b3b3b3; + font-size: 80%; + display: inline-block; +} + +@media screen and (max-width: 480px) { + .wy-breadcrumbs-extra { + display: none; + } + + .wy-breadcrumbs li.wy-breadcrumbs-aside { + display: none; + } +} +@media print { + .wy-breadcrumbs li.wy-breadcrumbs-aside { + display: none; + } +} +.wy-affix { + position: fixed; + top: 1.618em; +} + +.wy-menu a:hover { + text-decoration: none; +} + +.wy-menu-horiz { + *zoom: 1; +} +.wy-menu-horiz:before, .wy-menu-horiz:after { + display: table; + content: ""; +} +.wy-menu-horiz:after { + clear: both; +} +.wy-menu-horiz ul, .wy-menu-horiz li { + display: inline-block; +} +.wy-menu-horiz li:hover { + background: rgba(255, 255, 255, 0.1); +} +.wy-menu-horiz li.divide-left { + border-left: solid 1px #404040; +} +.wy-menu-horiz li.divide-right { + border-right: solid 1px #404040; +} +.wy-menu-horiz a { + height: 32px; + display: inline-block; + line-height: 32px; + padding: 0 16px; +} + +.wy-menu-vertical header { + height: 32px; + display: inline-block; + line-height: 32px; + padding: 0 1.618em; + display: block; + font-weight: bold; + text-transform: uppercase; + font-size: 80%; + color: #2980b9; + white-space: nowrap; +} +.wy-menu-vertical ul { + margin-bottom: 0; +} +.wy-menu-vertical li.divide-top { + border-top: solid 1px #404040; +} +.wy-menu-vertical li.divide-bottom { + border-bottom: solid 1px #404040; +} +.wy-menu-vertical li.current { + background: #e3e3e3; +} +.wy-menu-vertical li.current a { + color: gray; + border-right: solid 1px #c9c9c9; + padding: 0.4045em 2.427em; +} +.wy-menu-vertical li.current a:hover { + background: #d6d6d6; +} +.wy-menu-vertical li.on a, .wy-menu-vertical li.current > a { + color: #404040; + padding: 0.4045em 1.618em; + font-weight: bold; + position: relative; + background: #fcfcfc; + border: none; + border-bottom: solid 1px #c9c9c9; + border-top: solid 1px #c9c9c9; + padding-left: 1.618em -4px; +} +.wy-menu-vertical li.on a:hover, .wy-menu-vertical li.current > a:hover { + background: #fcfcfc; +} +.wy-menu-vertical li.toctree-l2.current > a { + background: #c9c9c9; + padding: 0.4045em 2.427em; +} +.wy-menu-vertical li.current ul { + display: block; +} +.wy-menu-vertical li ul { + margin-bottom: 0; + display: none; +} +.wy-menu-vertical .local-toc li ul { + display: block; +} +.wy-menu-vertical li ul li a { + margin-bottom: 0; + color: #b3b3b3; + font-weight: normal; +} +.wy-menu-vertical a { + display: inline-block; + line-height: 18px; + padding: 0.4045em 1.618em; + display: block; + position: relative; + font-size: 90%; + color: #b3b3b3; +} +.wy-menu-vertical a:hover { + background-color: #4e4a4a; + cursor: pointer; +} +.wy-menu-vertical a:active { + background-color: #2980b9; + cursor: pointer; + color: white; +} + +.wy-side-nav-search { + z-index: 200; + background-color: #2980b9; + text-align: center; + padding: 0.809em; + display: block; + color: #fcfcfc; + margin-bottom: 0.809em; +} +.wy-side-nav-search input[type=text] { + width: 100%; + border-radius: 50px; + padding: 6px 12px; + border-color: #2472a4; +} +.wy-side-nav-search img { + display: block; + margin: auto auto 0.809em auto; + height: 45px; + width: 45px; + background-color: #2980b9; + padding: 5px; + border-radius: 100%; +} +.wy-side-nav-search > a, .wy-side-nav-search .wy-dropdown > a { + color: #fcfcfc; + font-size: 100%; + font-weight: bold; + display: inline-block; + padding: 4px 6px; + margin-bottom: 0.809em; +} +.wy-side-nav-search > a:hover, .wy-side-nav-search .wy-dropdown > a:hover { + background: rgba(255, 255, 255, 0.1); +} + +.wy-nav .wy-menu-vertical header { + color: #2980b9; +} +.wy-nav .wy-menu-vertical a { + color: #b3b3b3; +} +.wy-nav .wy-menu-vertical a:hover { + background-color: #2980b9; + color: white; +} + +[data-menu-wrap] { + -webkit-transition: all 0.2s ease-in; + -moz-transition: all 0.2s ease-in; + transition: all 0.2s ease-in; + position: absolute; + opacity: 1; + width: 100%; + opacity: 0; +} +[data-menu-wrap].move-center { + left: 0; + right: auto; + opacity: 1; +} +[data-menu-wrap].move-left { + right: auto; + left: -100%; + opacity: 0; +} +[data-menu-wrap].move-right { + right: -100%; + left: auto; + opacity: 0; +} + +.wy-body-for-nav { + background: left repeat-y #fcfcfc; + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxOERBMTRGRDBFMUUxMUUzODUwMkJCOThDMEVFNURFMCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoxOERBMTRGRTBFMUUxMUUzODUwMkJCOThDMEVFNURFMCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjE4REExNEZCMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjE4REExNEZDMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+EwrlwAAAAA5JREFUeNpiMDU0BAgwAAE2AJgB9BnaAAAAAElFTkSuQmCC); + background-size: 300px 1px; +} + +.wy-grid-for-nav { + position: absolute; + width: 100%; + height: 100%; +} + +.wy-nav-side { + position: absolute; + top: 0; + left: 0; + width: 300px; + overflow: hidden; + min-height: 100%; + background: #343131; + z-index: 200; +} + +.wy-nav-top { + display: none; + background: #2980b9; + color: white; + padding: 0.4045em 0.809em; + position: relative; + line-height: 50px; + text-align: center; + font-size: 100%; + *zoom: 1; +} +.wy-nav-top:before, .wy-nav-top:after { + display: table; + content: ""; +} +.wy-nav-top:after { + clear: both; +} +.wy-nav-top a { + color: white; + font-weight: bold; +} +.wy-nav-top img { + margin-right: 12px; + height: 45px; + width: 45px; + background-color: #2980b9; + padding: 5px; + border-radius: 100%; +} +.wy-nav-top i { + font-size: 30px; + float: left; + cursor: pointer; +} + +.wy-nav-content-wrap { + margin-left: 300px; + background: #fcfcfc; + min-height: 100%; +} + +.wy-nav-content { + padding: 1.618em 3.236em; + height: 100%; + max-width: 800px; + margin: auto; +} + +.wy-body-mask { + position: fixed; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.2); + display: none; + z-index: 499; +} +.wy-body-mask.on { + display: block; +} + +footer { + color: #999999; +} +footer p { + margin-bottom: 12px; +} + +.rst-footer-buttons { + *zoom: 1; +} +.rst-footer-buttons:before, .rst-footer-buttons:after { + display: table; + content: ""; +} +.rst-footer-buttons:after { + clear: both; +} + +#search-results .search li { + margin-bottom: 24px; + border-bottom: solid 1px #e1e4e5; + padding-bottom: 24px; +} +#search-results .search li:first-child { + border-top: solid 1px #e1e4e5; + padding-top: 24px; +} +#search-results .search li a { + font-size: 120%; + margin-bottom: 12px; + display: inline-block; +} +#search-results .context { + color: gray; + font-size: 90%; +} + +@media screen and (max-width: 768px) { + .wy-body-for-nav { + background: #fcfcfc; + } + + .wy-nav-top { + display: block; + } + + .wy-nav-side { + left: -300px; + } + .wy-nav-side.shift { + width: 85%; + left: 0; + } + + .wy-nav-content-wrap { + margin-left: 0; + } + .wy-nav-content-wrap .wy-nav-content { + padding: 1.618em; + } + .wy-nav-content-wrap.shift { + position: fixed; + min-width: 100%; + left: 85%; + top: 0; + height: 100%; + overflow: hidden; + } +} +@media screen and (min-width: 1400px) { + .wy-nav-content-wrap { + background: rgba(0, 0, 0, 0.05); + } + + .wy-nav-content { + margin: 0; + background: #fcfcfc; + } +} +@media print { + .wy-nav-side { + display: none; + } + + .wy-nav-content-wrap { + margin-left: 0; + } +} +nav.stickynav { + position: fixed; + top: 0; +} + +.rst-versions { + position: fixed; + bottom: 0; + left: 0; + width: 300px; + color: #fcfcfc; + background: #1f1d1d; + border-top: solid 10px #343131; + font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; + z-index: 400; +} +.rst-versions a { + color: #2980b9; + text-decoration: none; +} +.rst-versions .rst-badge-small { + display: none; +} +.rst-versions .rst-current-version { + padding: 12px; + background-color: #272525; + display: block; + text-align: right; + font-size: 90%; + cursor: pointer; + color: #27ae60; + *zoom: 1; +} +.rst-versions .rst-current-version:before, .rst-versions .rst-current-version:after { + display: table; + content: ""; +} +.rst-versions .rst-current-version:after { + clear: both; +} +.rst-versions .rst-current-version .fa, .rst-versions .rst-current-version .wy-dropdown .caret, .wy-dropdown .rst-versions .rst-current-version .caret, .rst-versions .rst-current-version .wy-inline-validate.wy-inline-validate-success .wy-input-context, .wy-inline-validate.wy-inline-validate-success .rst-versions .rst-current-version .wy-input-context, .rst-versions .rst-current-version .wy-inline-validate.wy-inline-validate-danger .wy-input-context, .wy-inline-validate.wy-inline-validate-danger .rst-versions .rst-current-version .wy-input-context, .rst-versions .rst-current-version .wy-inline-validate.wy-inline-validate-warning .wy-input-context, .wy-inline-validate.wy-inline-validate-warning .rst-versions .rst-current-version .wy-input-context, .rst-versions .rst-current-version .wy-inline-validate.wy-inline-validate-info .wy-input-context, .wy-inline-validate.wy-inline-validate-info .rst-versions .rst-current-version .wy-input-context, .rst-versions .rst-current-version .wy-tag-input-group .wy-tag .wy-tag-remove, .wy-tag-input-group .wy-tag .rst-versions .rst-current-version .wy-tag-remove, .rst-versions .rst-current-version .rst-content .admonition-title, .rst-content .rst-versions .rst-current-version .admonition-title, .rst-versions .rst-current-version .rst-content h1 .headerlink, .rst-content h1 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h2 .headerlink, .rst-content h2 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h3 .headerlink, .rst-content h3 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h4 .headerlink, .rst-content h4 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h5 .headerlink, .rst-content h5 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h6 .headerlink, .rst-content h6 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content dl dt .headerlink, .rst-content dl dt .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .icon { + color: #fcfcfc; +} +.rst-versions .rst-current-version .fa-book, .rst-versions .rst-current-version .icon-book { + float: left; +} +.rst-versions .rst-current-version .icon-book { + float: left; +} +.rst-versions .rst-current-version.rst-out-of-date { + background-color: #e74c3c; + color: white; +} +.rst-versions .rst-current-version.rst-active-old-version { + background-color: #f1c40f; + color: black; +} +.rst-versions.shift-up .rst-other-versions { + display: block; +} +.rst-versions .rst-other-versions { + font-size: 90%; + padding: 12px; + color: gray; + display: none; +} +.rst-versions .rst-other-versions hr { + display: block; + height: 1px; + border: 0; + margin: 20px 0; + padding: 0; + border-top: solid 1px #413d3d; +} +.rst-versions .rst-other-versions dd { + display: inline-block; + margin: 0; +} +.rst-versions .rst-other-versions dd a { + display: inline-block; + padding: 6px; + color: #fcfcfc; +} +.rst-versions.rst-badge { + width: auto; + bottom: 20px; + right: 20px; + left: auto; + border: none; + max-width: 300px; +} +.rst-versions.rst-badge .icon-book { + float: none; +} +.rst-versions.rst-badge .fa-book, .rst-versions.rst-badge .icon-book { + float: none; +} +.rst-versions.rst-badge.shift-up .rst-current-version { + text-align: right; +} +.rst-versions.rst-badge.shift-up .rst-current-version .fa-book, .rst-versions.rst-badge.shift-up .rst-current-version .icon-book { + float: left; +} +.rst-versions.rst-badge.shift-up .rst-current-version .icon-book { + float: left; +} +.rst-versions.rst-badge .rst-current-version { + width: auto; + height: 30px; + line-height: 30px; + padding: 0 6px; + display: block; + text-align: center; +} + +@media screen and (max-width: 768px) { + .rst-versions { + width: 85%; + display: none; + } + .rst-versions.shift { + display: block; + } + + img { + width: 100%; + height: auto; + } +} +.rst-content img { + max-width: 100%; + height: auto !important; +} +.rst-content div.figure { + margin-bottom: 24px; +} +.rst-content div.figure.align-center { + text-align: center; +} +.rst-content .section > img { + margin-bottom: 24px; +} +.rst-content blockquote { + margin-left: 24px; + line-height: 24px; + margin-bottom: 24px; +} +.rst-content .note .last, .rst-content .attention .last, .rst-content .caution .last, .rst-content .danger .last, .rst-content .error .last, .rst-content .hint .last, .rst-content .important .last, .rst-content .tip .last, .rst-content .warning .last, .rst-content .seealso .last { + margin-bottom: 0; +} +.rst-content .admonition-title:before { + margin-right: 4px; +} +.rst-content .admonition table { + border-color: rgba(0, 0, 0, 0.1); +} +.rst-content .admonition table td, .rst-content .admonition table th { + background: transparent !important; + border-color: rgba(0, 0, 0, 0.1) !important; +} +.rst-content .section ol.loweralpha, .rst-content .section ol.loweralpha li { + list-style: lower-alpha; +} +.rst-content .section ol.upperalpha, .rst-content .section ol.upperalpha li { + list-style: upper-alpha; +} +.rst-content .section ol p, .rst-content .section ul p { + margin-bottom: 12px; +} +.rst-content .line-block { + margin-left: 24px; +} +.rst-content .topic-title { + font-weight: bold; + margin-bottom: 12px; +} +.rst-content .toc-backref { + color: #404040; +} +.rst-content .align-right { + float: right; + margin: 0px 0px 24px 24px; +} +.rst-content .align-left { + float: left; + margin: 0px 24px 24px 0px; +} +.rst-content .align-center { + margin: auto; + display: block; +} +.rst-content h1 .headerlink, .rst-content h2 .headerlink, .rst-content h3 .headerlink, .rst-content h4 .headerlink, .rst-content h5 .headerlink, .rst-content h6 .headerlink, .rst-content dl dt .headerlink { + display: none; + visibility: hidden; + font-size: 14px; +} +.rst-content h1 .headerlink:after, .rst-content h2 .headerlink:after, .rst-content h3 .headerlink:after, .rst-content h4 .headerlink:after, .rst-content h5 .headerlink:after, .rst-content h6 .headerlink:after, .rst-content dl dt .headerlink:after { + visibility: visible; + content: "\f0c1"; + font-family: FontAwesome; + display: inline-block; +} +.rst-content h1:hover .headerlink, .rst-content h2:hover .headerlink, .rst-content h3:hover .headerlink, .rst-content h4:hover .headerlink, .rst-content h5:hover .headerlink, .rst-content h6:hover .headerlink, .rst-content dl dt:hover .headerlink { + display: inline-block; +} +.rst-content .sidebar { + float: right; + width: 40%; + display: block; + margin: 0 0 24px 24px; + padding: 24px; + background: #f3f6f6; + border: solid 1px #e1e4e5; +} +.rst-content .sidebar p, .rst-content .sidebar ul, .rst-content .sidebar dl { + font-size: 90%; +} +.rst-content .sidebar .last { + margin-bottom: 0; +} +.rst-content .sidebar .sidebar-title { + display: block; + font-family: "Roboto Slab", "ff-tisa-web-pro", "Georgia", Arial, sans-serif; + font-weight: bold; + background: #e1e4e5; + padding: 6px 12px; + margin: -24px; + margin-bottom: 24px; + font-size: 100%; +} +.rst-content .highlighted { + background: #f1c40f; + display: inline-block; + font-weight: bold; + padding: 0 6px; +} +.rst-content .footnote-reference, .rst-content .citation-reference { + vertical-align: super; + font-size: 90%; +} +.rst-content table.docutils.citation, .rst-content table.docutils.footnote { + background: none; + border: none; + color: #999999; +} +.rst-content table.docutils.citation td, .rst-content table.docutils.citation tr, .rst-content table.docutils.footnote td, .rst-content table.docutils.footnote tr { + border: none; + background-color: transparent !important; + white-space: normal; +} +.rst-content table.docutils.citation td.label, .rst-content table.docutils.footnote td.label { + padding-left: 0; + padding-right: 0; + vertical-align: top; +} +.rst-content table.field-list { + border: none; +} +.rst-content table.field-list td { + border: none; + padding-top: 5px; +} +.rst-content table.field-list .field-name { + padding-right: 10px; + text-align: left; + white-space: nowrap; +} +.rst-content table.field-list .field-body { + text-align: left; + padding-left: 0; +} +.rst-content tt { + color: black; +} +.rst-content tt big, .rst-content tt em { + font-size: 100% !important; + line-height: normal; +} +.rst-content tt .xref, a .rst-content tt { + font-weight: bold; +} +.rst-content a tt { + color: #2980b9; +} +.rst-content dl { + margin-bottom: 24px; +} +.rst-content dl dt { + font-weight: bold; +} +.rst-content dl p, .rst-content dl table, .rst-content dl ul, .rst-content dl ol { + margin-bottom: 12px !important; +} +.rst-content dl dd { + margin: 0 0 12px 24px; +} +.rst-content dl:not(.docutils) { + margin-bottom: 24px; +} +.rst-content dl:not(.docutils) dt { + display: inline-block; + margin: 6px 0; + font-size: 90%; + line-height: normal; + background: #e7f2fa; + color: #2980b9; + border-top: solid 3px #6ab0de; + padding: 6px; + position: relative; +} +.rst-content dl:not(.docutils) dt:before { + color: #6ab0de; +} +.rst-content dl:not(.docutils) dt .headerlink { + color: #404040; + font-size: 100% !important; +} +.rst-content dl:not(.docutils) dl dt { + margin-bottom: 6px; + border: none; + border-left: solid 3px #cccccc; + background: #f0f0f0; + color: gray; +} +.rst-content dl:not(.docutils) dl dt .headerlink { + color: #404040; + font-size: 100% !important; +} +.rst-content dl:not(.docutils) dt:first-child { + margin-top: 0; +} +.rst-content dl:not(.docutils) tt { + font-weight: bold; +} +.rst-content dl:not(.docutils) tt.descname, .rst-content dl:not(.docutils) tt.descclassname { + background-color: transparent; + border: none; + padding: 0; + font-size: 100% !important; +} +.rst-content dl:not(.docutils) tt.descname { + font-weight: bold; +} +.rst-content dl:not(.docutils) .optional { + display: inline-block; + padding: 0 4px; + color: black; + font-weight: bold; +} +.rst-content dl:not(.docutils) .property { + display: inline-block; + padding-right: 8px; +} +.rst-content .viewcode-link, .rst-content .viewcode-back { + display: inline-block; + color: #27ae60; + font-size: 80%; + padding-left: 24px; +} +.rst-content .viewcode-back { + display: block; + float: right; +} + +@media screen and (max-width: 480px) { + .rst-content .sidebar { + width: 100%; + } +} +span[id*='MathJax-Span'] { + color: #404040; +} diff --git a/docs/_themes/sphinx_rtd_theme/static/fonts/FontAwesome.otf b/docs/_themes/sphinx_rtd_theme/static/fonts/FontAwesome.otf new file mode 100644 index 0000000..8b0f54e Binary files /dev/null and b/docs/_themes/sphinx_rtd_theme/static/fonts/FontAwesome.otf differ diff --git a/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.eot b/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.eot new file mode 100644 index 0000000..7c79c6a Binary files /dev/null and b/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.eot differ diff --git a/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg b/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg new file mode 100644 index 0000000..45fdf33 --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg @@ -0,0 +1,414 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.ttf b/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.ttf new file mode 100644 index 0000000..e89738d Binary files /dev/null and b/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.ttf differ diff --git a/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.woff b/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.woff new file mode 100644 index 0000000..8c1748a Binary files /dev/null and b/docs/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.woff differ diff --git a/docs/_themes/sphinx_rtd_theme/static/js/theme.js b/docs/_themes/sphinx_rtd_theme/static/js/theme.js new file mode 100644 index 0000000..60520cc --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/static/js/theme.js @@ -0,0 +1,47 @@ +$( document ).ready(function() { + // Shift nav in mobile when clicking the menu. + $(document).on('click', "[data-toggle='wy-nav-top']", function() { + $("[data-toggle='wy-nav-shift']").toggleClass("shift"); + $("[data-toggle='rst-versions']").toggleClass("shift"); + }); + // Close menu when you click a link. + $(document).on('click', ".wy-menu-vertical .current ul li a", function() { + $("[data-toggle='wy-nav-shift']").removeClass("shift"); + $("[data-toggle='rst-versions']").toggleClass("shift"); + }); + $(document).on('click', "[data-toggle='rst-current-version']", function() { + $("[data-toggle='rst-versions']").toggleClass("shift-up"); + }); + // Make tables responsive + $("table.docutils:not(.field-list)").wrap("
"); +}); + +window.SphinxRtdTheme = (function (jquery) { + var stickyNav = (function () { + var navBar, + win, + stickyNavCssClass = 'stickynav', + applyStickNav = function () { + if (navBar.height() <= win.height()) { + navBar.addClass(stickyNavCssClass); + } else { + navBar.removeClass(stickyNavCssClass); + } + }, + enable = function () { + applyStickNav(); + win.on('resize', applyStickNav); + }, + init = function () { + navBar = jquery('nav.wy-nav-side:first'); + win = jquery(window); + }; + jquery(init); + return { + enable : enable + }; + }()); + return { + StickyNav : stickyNav + }; +}($)); diff --git a/docs/_themes/sphinx_rtd_theme/theme.conf b/docs/_themes/sphinx_rtd_theme/theme.conf new file mode 100644 index 0000000..1ad1fa7 --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/theme.conf @@ -0,0 +1,9 @@ +[theme] +inherit = basic +stylesheet = css/theme.css + +[options] +typekit_id = hiw1hhg +analytics_id = +sticky_navigation = False +github_fork = hgrecco/pyvisa diff --git a/docs/_themes/sphinx_rtd_theme/versions.html b/docs/_themes/sphinx_rtd_theme/versions.html new file mode 100644 index 0000000..8b3eb79 --- /dev/null +++ b/docs/_themes/sphinx_rtd_theme/versions.html @@ -0,0 +1,37 @@ +{% if READTHEDOCS %} +{# Add rst-badge after rst-versions for small badge style. #} +
+ + Read the Docs + v: {{ current_version }} + + +
+
+
Versions
+ {% for slug, url in versions %} +
{{ slug }}
+ {% endfor %} +
+
+
Downloads
+ {% for type, url in downloads %} +
{{ type }}
+ {% endfor %} +
+
+
On Read the Docs
+
+ Project Home +
+
+ Builds +
+
+
+ Free document hosting provided by Read the Docs. + +
+
+{% endif %} + diff --git a/docs/api/constants.rst b/docs/api/constants.rst new file mode 100644 index 0000000..398ad1c --- /dev/null +++ b/docs/api/constants.rst @@ -0,0 +1,45 @@ +.. _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: diff --git a/docs/api/index.rst b/docs/api/index.rst new file mode 100644 index 0000000..88227de --- /dev/null +++ b/docs/api/index.rst @@ -0,0 +1,14 @@ +.. _api: + +=== +API +=== + + +.. toctree:: + :maxdepth: 1 + + visalibrarybase + resourcemanager + resources + constants diff --git a/docs/api/resourcemanager.rst b/docs/api/resourcemanager.rst new file mode 100644 index 0000000..a4cd468 --- /dev/null +++ b/docs/api/resourcemanager.rst @@ -0,0 +1,9 @@ +.. _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 diff --git a/docs/api/resources.rst b/docs/api/resources.rst new file mode 100644 index 0000000..54dd5bc --- /dev/null +++ b/docs/api/resources.rst @@ -0,0 +1,135 @@ +.. _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: + diff --git a/docs/api/visalibrarybase.rst b/docs/api/visalibrarybase.rst new file mode 100644 index 0000000..df8a24d --- /dev/null +++ b/docs/api/visalibrarybase.rst @@ -0,0 +1,9 @@ +.. _api_visalibrarybase: + + +Visa Library +------------ + +.. autoclass:: pyvisa.highlevel.VisaLibraryBase + :members: + diff --git a/docs/architecture.rst b/docs/architecture.rst new file mode 100644 index 0000000..fafe3be --- /dev/null +++ b/docs/architecture.rst @@ -0,0 +1,120 @@ +.. _architecture: + +Architecture +============ + +PyVISA implements convenient and Pythonic programming in three layers: + + 1. Low-level: A wrapper around the shared visa library. + + The wrapper defines the argument types and response types of each function, + as well as the conversions between Python objects and foreign types. + + You will normally not need to access these functions directly. If you do, + it probably means that we need to improve layer 2. + + All level 1 functions are **static methods** of + :class:`pyvisa.highlevel.VisaLibrary`. + + .. warning:: + + Notice however that low-level functions might not be present in all + backends. For broader compatibility, do no use this layer. All the + functionality should is available via the next layer. + + + 2. Middle-level: A wrapping Python function for each function of the shared + visa library. + + These functions call the low-level functions, adding some code to deal with + type conversions for functions that return values by reference. + These functions also have comprehensive and Python friendly documentation. + + You only need to access this layer if you want to control certain specific + aspects of the VISA library which are not implemented by the corresponding + resource class. + + All level 2 functions are **bound methods** of + :class:`pyvisa.highlevel.VisaLibrary`. + + 3. High-level: An object-oriented layer for + :class:`pyvisa.highlevel.ResourceManager` and + :class:`pyvisa.resources.Resource` + + The ``ResourceManager`` implements methods to inspect connected resources. + You also use this object to open other resources instantiating the + appropriate ``Resource`` derived classes. + + ``Resource`` and the derived classes implement functions and attributes + access to the underlying resources in a Pythonic way. + +Most of the time you will only need to instantiate a ``ResourceManager``. For a +given resource, you will use the +:meth:`pyvisa.highlevel.ResourceManager.open_resource` method to obtain the +appropriate object. If needed, you will be able to access the ``VisaLibrary`` +object directly using the :attr:`pyvisa.highlevel.ResourceManager.visalib` +attribute. + +The ``VisaLibrary`` does the low-level calls. In the default NI Backend, +levels 1 and 2 are implemented in the same package called +:mod:`pyvisa.ctwrapper` (which stands for ctypes wrapper). This package is +included in PyVISA. + +Other backends can be used just by passing the name of the backend to +``ResourceManager`` after the `@` symbol. See more information in +:ref:`backends`. + + +Calling middle- and low-level functions +--------------------------------------- + +After you have instantiated the ``ResourceManager``:: + + >>> import visa + >>> rm = visa.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. + diff --git a/docs/backends.rst b/docs/backends.rst new file mode 100644 index 0000000..43b1b23 --- /dev/null +++ b/docs/backends.rst @@ -0,0 +1,196 @@ +.. _backends: + + +A frontend for multiple backends +================================ + +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 NI-VISA is the default backend (called **ni**) and is bundled with +PyVISA for simplicity. + +You can specify the backend to use when you instantiate the resource manager +using the ``@`` symbol. Remembering that **ni** is the default, this:: + + >>> import visa + >>> rm = visa.ResourceManager() + +is the same as this:: + + >>> import visa + >>> rm = visa.ResourceManager('@ni') + +You can still provide the path to the library if needed:: + + >>> import visa + >>> rm = visa.ResourceManager('/path/to/lib@ni') + +Under the hood, the :class:`pyvisa.highlevel.ResourceManager` looks for the +requested backend and instantiate the VISA library that it provides. + +PyVISA locates backends by name. If you do: + + >>> import visa + >>> rm = visa.ResourceManager('@somename') + +PyVISA will try to import a package/module named ``pyvisa-somename`` which +should be installed in your system. This is a loosly 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:: + + python -m visa 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 +``python -m visa info`` or ``pyvisa-info`` + +.. note:: + + Your backend name should not end by ``-script`` or it will be discarded. + This is because any script generated by setuptools containing the name + pyvisa will be named ``pyvisa-*-script`` and they are obviously not backends. + Examples are the ``pyvisa-shell`` and ``pyvisa-info`` scripts. + +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:`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. + + +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): + diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..096e536 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,297 @@ +# -*- 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 os +import pkg_resources +import datetime + + +# 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.0' + +# 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'] + +# 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 = pkg_resources.get_distribution(project).version +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 = ['_build'] + +# 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 = [] +html_theme_path = ['_themes'] + +# 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 = {} +html_sidebars = { + 'index': ['sidebarintro.html', 'sourcelink.html', 'searchbox.html'], + '**': ['sidebarlogo.html', 'localtoc.html', 'relations.html', + 'sourcelink.html', 'searchbox.html'] +} + +# 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)} diff --git a/docs/configuring.rst b/docs/configuring.rst new file mode 100644 index 0000000..02bce68 --- /dev/null +++ b/docs/configuring.rst @@ -0,0 +1,77 @@ +.. _configuring: + +Configuring the backend +============================ + +Currently there are two backends available: The one included in pyvisa, which +uses the NI library, 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 NI backend if the NI 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 NI backend +========================== + +.. note:: + + The NI backend requires that you install first the NI-VISA library. You can + get info here: (:ref:`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 :class:`pyvisa.highlevel.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. + +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:\\Python27\\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 diff --git a/docs/contributing.rst b/docs/contributing.rst new file mode 100644 index 0000000..13a104a --- /dev/null +++ b/docs/contributing.rst @@ -0,0 +1,76 @@ +.. _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:: + + python -m visa info + +It is useful that you also provide the log output. To obtain it, add the following lines to your code:: + + import visa + visa.log_to_screen() + + +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 either clone the public repository:: + + $ git clone git://github.com/pyvisa/pyvisa.git + +Download the tarball:: + + $ curl -OL https://github.com/pyvisa/pyvisa/tarball/master + +Or, download the zipball:: + + $ curl -OL https://github.com/pyvisa/pyvisa/zipball/master + +Once you have a copy of the source, you can embed it in your Python package, or install it into your site-packages easily:: + + $ python setup.py install + + +.. note:: If you have an old system installation of Python and you don't want to + mess with it, you can try `Anaconda CE`_. 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 CE`: https://store.continuum.io/cshop/anaconda +.. _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 + + diff --git a/docs/default.css b/docs/default.css new file mode 100644 index 0000000..2cfc4c8 --- /dev/null +++ b/docs/default.css @@ -0,0 +1,255 @@ +/* +:Author: David Goodger +:Contact: goodger@users.sourceforge.net +:Date: $Date$ +:Version: $Revision$ +:Copyright: This stylesheet has been placed in the public domain. + +Default cascading style sheet for the HTML output of Docutils. +*/ + +/* "! important" is used here to override other ``margin-top`` and + ``margin-bottom`` styles that are later in the stylesheet or + more specific. See http://www.w3.org/TR/CSS1#the-cascade */ +.first { + margin-top: 0 ! important } + +.last { + margin-bottom: 0 ! important } + +.hidden { + display: none } + +a.toc-backref { + text-decoration: none ; + color: black } + +blockquote.epigraph { + margin: 2em 5em ; } + +dl.docutils dd { + margin-bottom: 0.5em } + +/* Uncomment (and remove this text!) to get bold-faced definition list terms +dl.docutils dt { + font-weight: bold } +*/ + +div.abstract { + margin: 2em 5em } + +div.abstract p.topic-title { + font-weight: bold ; + text-align: center } + +div.admonition, div.attention, div.caution, div.danger, div.error, +div.hint, div.important, div.note, div.tip, div.warning { + margin: 2em ; + border: medium outset ; + padding: 1em } + +div.admonition p.admonition-title, div.hint p.admonition-title, +div.important p.admonition-title, div.note p.admonition-title, +div.tip p.admonition-title { + font-weight: bold ; + font-family: sans-serif } + +div.attention p.admonition-title, div.caution p.admonition-title, +div.danger p.admonition-title, div.error p.admonition-title, +div.warning p.admonition-title { + color: red ; + font-weight: bold ; + font-family: sans-serif } + +/* Uncomment (and remove this text!) to get reduced vertical space in + compound paragraphs. +div.compound .compound-first, div.compound .compound-middle { + margin-bottom: 0.5em } + +div.compound .compound-last, div.compound .compound-middle { + margin-top: 0.5em } +*/ + +div.dedication { + margin: 2em 5em ; + text-align: center ; + font-style: italic } + +div.dedication p.topic-title { + font-weight: bold ; + font-style: normal } + +div.figure { + margin-left: 2em } + +div.footer, div.header { + font-size: smaller } + +div.line-block { + display: block ; + margin-top: 1em ; + margin-bottom: 1em } + +div.line-block div.line-block { + margin-top: 0 ; + margin-bottom: 0 ; + margin-left: 1.5em } + +div.sidebar { + margin-left: 1em ; + border: medium outset ; + padding: 1em ; + background-color: #ffffee ; + width: 40% ; + float: right ; + clear: right } + +div.sidebar p.rubric { + font-family: sans-serif ; + font-size: medium } + +div.system-messages { + margin: 5em } + +div.system-messages h1 { + color: red } + +div.system-message { + border: medium outset ; + padding: 1em } + +div.system-message p.system-message-title { + color: red ; + font-weight: bold } + +div.topic { + margin: 2em } + +h1.title { + text-align: center } + +h2.subtitle { + text-align: center } + +hr.docutils { + width: 75% } + +ol.simple, ul.simple { + margin-bottom: 1em } + +ol.arabic { + list-style: decimal } + +ol.loweralpha { + list-style: lower-alpha } + +ol.upperalpha { + list-style: upper-alpha } + +ol.lowerroman { + list-style: lower-roman } + +ol.upperroman { + list-style: upper-roman } + +p.attribution { + text-align: right ; + margin-left: 50% } + +p.caption { + font-style: italic } + +p.credits { + font-style: italic ; + font-size: smaller } + +p.label { + white-space: nowrap } + +p.rubric { + font-weight: bold ; + font-size: larger ; + color: maroon ; + text-align: center } + +p.sidebar-title { + font-family: sans-serif ; + font-weight: bold ; + font-size: larger } + +p.sidebar-subtitle { + font-family: sans-serif ; + font-weight: bold } + +p.topic-title { + font-weight: bold } + +pre.address { + margin-bottom: 0 ; + margin-top: 0 ; + font-family: serif ; + font-size: 100% } + +pre.line-block { + font-family: serif ; + font-size: 100% } + +pre.literal-block, pre.doctest-block { + margin-left: 2em ; + margin-right: 2em ; + background-color: #eeeeee } + +span.classifier { + font-family: sans-serif ; + font-style: oblique } + +span.classifier-delimiter { + font-family: sans-serif ; + font-weight: bold } + +span.interpreted { + font-family: sans-serif } + +span.option { + white-space: nowrap } + +span.pre { + white-space: pre } + +span.problematic { + color: red } + +table.citation { + border-left: solid thin gray } + +table.docinfo { + margin: 2em 4em } + +table.docutils { + margin-top: 0.5em ; + margin-bottom: 0.5em } + +table.footnote { + border-left: solid thin black } + +table.docutils td, table.docutils th, +table.docinfo td, table.docinfo th { + padding-left: 0.5em ; + padding-right: 0.5em ; + vertical-align: top } + +table.docutils th.field-name, table.docinfo th.docinfo-name { + font-weight: bold ; + text-align: left ; + white-space: nowrap ; + padding-left: 0 } + +h1 tt.docutils, h2 tt.docutils, h3 tt.docutils, +h4 tt.docutils, h5 tt.docutils, h6 tt.docutils { + font-size: 100% } + +tt.docutils { + background-color: #eeeeee } + +ul.auto-toc { + list-style-type: none } diff --git a/docs/example.rst b/docs/example.rst new file mode 100644 index 0000000..78fe601 --- /dev/null +++ b/docs/example.rst @@ -0,0 +1,72 @@ + + +.. _sec:more-complex-example: + +A more complex example +====================== + +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 initialise +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 initialisation 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; 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; feed:control next") + +That's it. 18 lines of lucid code. (Well, SCPI is awkward, but +that's another story.) diff --git a/docs/faq.rst b/docs/faq.rst new file mode 100644 index 0000000..b23146a --- /dev/null +++ b/docs/faq.rst @@ -0,0 +1,177 @@ +.. _faq: + +Frequently asked 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 is currently maintained by Hernan E. Grecco . + +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 visa + visa.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:: + + python -m visa 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:`configuring`. + + +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:: + + python -m visa 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:`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. + + +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/ diff --git a/docs/getting.rst b/docs/getting.rst new file mode 100644 index 0000000..e89baf1 --- /dev/null +++ b/docs/getting.rst @@ -0,0 +1,84 @@ +.. _getting: + +Installation +============ + +PyVISA is a frontend to the VISA library. It runs on Python 2.7 and 3.4+. + +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:`getting_nivisa`). There are multiple VISA implementations from +different vendors. PyVISA is tested only against +`National Instruments's VISA`_. + +.. 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 visa + >>> rm = visa.ResourceManager() + >>> print(rm.list_resources()) + +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`_ + + +Using the development version +----------------------------- + +You can install the latest development version (at your own risk) directly +form GitHub_:: + + $ pip install -U https://github.com/pyvisa/pyvisa/zipball/master + + +.. note:: + + If you have an old system installation of Python and you don't want to + mess with it, you can try `Anaconda CE`_. 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 CE`: https://store.continuum.io/cshop/anaconda +.. _PyPI: https://pypi.python.org/pypi/PyVISA +.. _GitHub: https://github.com/pyvisa/pyvisa +.. _`National Instruments's VISA`: http://ni.com/visa/ +.. _`issue tracker`: https://github.com/pyvisa/pyvisa/issues +.. _`PyVISA-Py`: http://pyvisa-py.readthedocs.io/en/latest/ diff --git a/docs/getting_nivisa.rst b/docs/getting_nivisa.rst new file mode 100644 index 0000000..1661878 --- /dev/null +++ b/docs/getting_nivisa.rst @@ -0,0 +1,90 @@ +.. _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):: + + python -m visa info + +or equivalently:: + + 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/ diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..a0dfb8c --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,90 @@ +: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 visa + >>> rm = visa.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`. + + +User guide +---------- + +.. toctree:: + :maxdepth: 1 + + getting + configuring + tutorial + rvalues + example + resources + backends + shell + architecture + +More information +---------------- + +.. toctree:: + :maxdepth: 1 + + names + migrating + contributing + faq + getting_nivisa + api/index + + +.. LocalWords: rst british reST ies vpp pyvisa docs pyvLab diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..6497cbf --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,190 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +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 diff --git a/docs/migrating.rst b/docs/migrating.rst new file mode 100644 index 0000000..761e81a --- /dev/null +++ b/docs/migrating.rst @@ -0,0 +1,294 @@ +.. _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 visa + >>> keithley = visa.instrument("GPIB::12") + >>> print(keithley.ask("*IDN?")) + +change it to: + + >>> import visa + >>> rm = visa.ResourceManager() + >>> keithley = rm.open_resource("GPIB::12") + >>> print(keithley.query("*IDN?")) + +**If you are doing:** + + >>> print(visa.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 visa + >>> rm = visa.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 = visa.VisaLibrary("/path/to/my/libvisa.so.7") + >>> lib2 = visa.VisaLibrary("/path/to/my/libvisa.so.7") + >>> lib3 = visa.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 = visa.VisaLibrary("/path/to/my/libvisa.so.7") + >>> rm = lib.resource_manager + +or equivalently: + + >>> rm = visa.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 visa + >>> rm = visa.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/ diff --git a/docs/names.rst b/docs/names.rst new file mode 100644 index 0000000..22609b8 --- /dev/null +++ b/docs/names.rst @@ -0,0 +1,157 @@ + +.. _resource_names: + +VISA resource names +=================== + +If you use the function :func:`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. +================================ ============================================= + diff --git a/docs/resources.rst b/docs/resources.rst new file mode 100644 index 0000000..031a65b --- /dev/null +++ b/docs/resources.rst @@ -0,0 +1,166 @@ +.. _resources: + +Resources +========= + +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 +:meth:`pyvisa.highlevel.ResourceManager.open_resource` method of a :class:`pyvisa.highlevel.ResourceManager`. In general terms, there +are two main groups derived from :class:`pyvisa.resources.Resource`, :class:`pyvisa.resources.RegisterBasedResource` and :class:`pyvisa.resources.MessageBasedResource`. + +.. 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 encounte more +often. For more information, refer to the :ref:`api`. + + +Attributes 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. + + +`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. 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. + diff --git a/docs/rvalues.rst b/docs/rvalues.rst new file mode 100644 index 0000000..a8b909e --- /dev/null +++ b/docs/rvalues.rst @@ -0,0 +1,205 @@ +.. _rvalues: + +Reading and Writing values +========================== + +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 two different methods for this +called :meth:`pyvisa.resources.MessageBasedResource.query_ascii_values` +and :meth:`pyvisa.resources.MessageBasedResource.query_binary_values`. +It also has the convenient :meth:`pyvisa.resources.MessageBasedResource.query_values` +which will use follow a previously established configuration. + + +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. + +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. + + +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) + + + +Preconfiguring the transfer format +---------------------------------- + +Most of the cases, each device will transfer data in the same format every time. +And making the call so detailed everytime can be annoying. For this purpose, +PyVISA provides a way to preconfigure the default. Each Message Based +Resources exposes an attribute named ``values_format`` which is an object with the following +properties: ``is_binary``, ``datatype``, ``is_big_endian``, ``container``. For example to set +e.g. little-endian doubles and a numpy array:: + + >>> inst.values_format.is_binary = True + >>> inst.values_format.datatype = 'd' + >>> inst.values_format.is_big_endian = False + >>> inst.values_format.container = numpy.array + +or shorter: + + >>> inst.values_format.use_binary('d', False, numpy.array) + +After doing this, you can simply call:: + + >>> inst.query_values('CURV?') + +which will dispatch to the appropriate function and arguments. + +If you want to default to ASCII transfer, preconfiguring is a little bit more +cumbersome as you need to specify the converters for both ways. + +For example with hex, with ``'$'`` as separator: + + >>> inst.values_format.is_binary = False + >>> inst.values_format.converter = 'x' + >>> inst.values_format.separator = '$' + >>> inst.values_format.container = numpy.array + +or shorter: + + >>> inst.values_format.use_ascii('x', '$', numpy.array) + + +This works for both query and write operations. + + +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. diff --git a/docs/shell.rst b/docs/shell.rst new file mode 100644 index 0000000..70d51e7 --- /dev/null +++ b/docs/shell.rst @@ -0,0 +1,213 @@ +.. _shell: + +PyVISA Shell +============ + +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:: + + python -m visa shell + +or:: + + 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:: + + +-----------------------------+------------+----------------------------+-------------------------------------+ + | 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:: + + python -m visa -b sim shell + +or:: + + 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:: + + python -m visa -b py shell + +or:: + + pyvisa-shell -b py + +uses python-py as backend instead of ni backend, for situation when ni not installed. + + +PyVisa Info +=========== + +You can invoke it from the command-line:: + + python -m visa info + +or:: + + 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 + diff --git a/docs/tutorial.rst b/docs/tutorial.rst new file mode 100644 index 0000000..b44cc6a --- /dev/null +++ b/docs/tutorial.rst @@ -0,0 +1,96 @@ +.. _tutorial: + +Tutorial +======== + +.. note:: If you have been using PyVISA before version 1.5, you might want to + read :ref:`migrating`. + + +An example +---------- + +Let's go *in medias res* and have a look at a simple example:: + + >>> import visa + >>> rm = visa.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 ``visa``, we create a ``ResourceManager`` object. If called +without arguments, PyVISA will use the default backend (NI) which tries to find +the VISA shared library for you. You can check, the location of the shared +library used 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:`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:`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 :py:meth:`~pyvisa.highlevel.ResourceManager.list_resources`. The +default value is '?*::INSTR' which means that by default only instrument +whose resource name ends with '::INSTR' (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()) + + +Example for serial (RS232) device +--------------------------------- + +Consider an Oxford ITC4 temperature controller, which is connected +through COM2 with my computer. The following code prints its +self-identification on the screen:: + + itc4 = rm.open_resource("COM2") + itc4.write("V") + print(itc4.read()) + +Instead of separate write and read operations, you can do both with +one ``query()`` call. Thus, the above source code is equivalent to:: + + print(itc4.query("V")) + +It couldn't be simpler. diff --git a/examples/itc4.py b/examples/itc4.py new file mode 100644 index 0000000..bd6e7cb --- /dev/null +++ b/examples/itc4.py @@ -0,0 +1,43 @@ +#!/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") diff --git a/examples/keithley2000.py b/examples/keithley2000.py new file mode 100644 index 0000000..aeea199 --- /dev/null +++ b/examples/keithley2000.py @@ -0,0 +1,51 @@ +#!/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") diff --git a/pyvisa/__init__.py b/pyvisa/__init__.py new file mode 100644 index 0000000..cd9d3bb --- /dev/null +++ b/pyvisa/__init__.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +""" + pyvisa + ~~~~~~ + + Python wrapper of National Instrument (NI) Virtual Instruments Software + Architecture library (VISA). + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import logging +import pkg_resources + +from . import compat +logger = logging.getLogger('pyvisa') +logger.addHandler(compat.NullHandler()) + + +def log_to_screen(level=logging.DEBUG): + logger.setLevel(level) + ch = logging.StreamHandler() + ch.setLevel(level) + + formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + + ch.setFormatter(formatter) + + logger.addHandler(ch) + + +__version__ = "unknown" +try: # pragma: no cover + __version__ = pkg_resources.get_distribution('pyvisa').version +except: # pragma: no cover + pass # we seem to have a local copy without any repository control or installed without setuptools + # so the reported version will be __unknown__ + + +from .highlevel import ResourceManager +from .errors import (Error, VisaIOError, VisaIOWarning, VisaTypeError, + UnknownHandler, OSNotSupported, InvalidBinaryFormat, + InvalidSession, LibraryError) +# This is needed to registry all resources. +from .resources import Resource +from . import ctwrapper diff --git a/pyvisa/attributes.py b/pyvisa/attributes.py new file mode 100644 index 0000000..95e429d --- /dev/null +++ b/pyvisa/attributes.py @@ -0,0 +1,3292 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.attributes + ~~~~~~~~~~~~~~~~~ + + Comprehensive of all properties. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +from collections import defaultdict + +from .compat import with_metaclass +from . import constants + +#: Not available value. +NotAvailable = object() + +#: Attribute for all session types. +AllSessionTypes = object() + + +#: Map resource to attribute +AttributesPerResource = defaultdict(set) +AttributesByID = dict() + + +class AttributeType(type): + """Base Type for Attributes + + Assigns the `attribute_id` and improves the documentation. + """ + + def __init__(cls, name, bases, dct): + super(AttributeType, cls).__init__(name, bases, dct) + if not 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 + + +class Attribute(with_metaclass(AttributeType)): + """Base class for Attributes to be used as Properties. + """ + + #: List of resource types with this attribute. + #: each element is a tuple (constants.InterfaceType, str) + resources = [] + + #: Name of the Python property to be matched to this attribute. + py_name = 'To be specified' + + #: Name of the VISA Attribute + visa_name = 'To be specified' + + #: Numeric constant of the VISA Attribute + attribute_id = 0 + + #: Default value fo the VISA Attribute + default = 'N/A' + + #: Access + read, write, local = False, False, False + + @classmethod + def redoc(cls): + cls.__doc__ += '\n:VISA Attribute: %s (%s)' % (cls.visa_name, + cls.attribute_id) + + def post_get(self, value): + """Override this method to check or modify the value returned by the VISA function. + + :param value: the value returned by the VISA library. + :return: the equivalent python value. + """ + return value + + def pre_set(self, value): + """Override this method to check or modify the value to be passed to the VISA function. + + :param value: the python value to be passed to VISA library. + :return: the equivalent value. + """ + return value + + def __get__(self, instance, owner): + 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, value): + if not self.write: + raise AttributeError("can't write attribute") + + instance.set_visa_attribute(self.attribute_id, self.pre_set(value)) + + @classmethod + def in_resource(cls, session_type): + """Returns True if the attribute is part of a given session type. + + The session_type is a tuple with the interface type and resource_class + + :type session_type: (constants.InterfaceType, str) + :rtype: bool + """ + if cls.resources is AllSessionTypes: + return True + return session_type in cls.resources + + +class EnumAttribute(Attribute): + """Class for attributes with values that map to a PyVISA Enum. + """ + + #: Enum type with valid values. + enum_type = None + + @classmethod + def redoc(cls): + super(EnumAttribute, cls).redoc() + cls.__doc__ += '\n:type: :class:%s.%s' % (cls.enum_type.__module__, + cls.enum_type.__name__) + + def post_get(self, value): + return self.enum_type(value) + + def pre_set(self, value): + if value not in self.enum_type: + 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): + super(IntAttribute, cls).redoc() + cls.__doc__ += '\n:type: int' + + def post_get(self, value): + 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, max_value, values = None, None, [] + + @classmethod + def redoc(cls): + 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): + 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 = [] + + @classmethod + def redoc(cls): + super(ValuesAttribute, cls).redoc() + cls.__doc__ += '\n:values: %s' % cls.values + + def pre_set(self, value): + 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. + """ + + @classmethod + def redoc(cls): + super(BooleanAttribute, cls).redoc() + cls.__doc__ += '\n:type: bool' + + def post_get(self, value): + return value == constants.VI_TRUE + + def pre_set(self, value): + return constants.VI_TRUE if value else constants.VI_FALSE + + +class CharAttribute(Attribute): + """Class for attributes with char values. + """ + + @classmethod + def redoc(cls): + super(CharAttribute, cls).redoc() + cls.__doc__ += '\n:range: 0 <= x <= 255\n:type: int' + + def post_get(self, value): + return chr(value) + + def pre_set(self, value): + return ord(value) + + +# noinspection PyPep8Naming +class AttrVI_ATTR_4882_COMPLIANT(BooleanAttribute): + """VI_ATTR_4882_COMPLIANT specifies 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_ALLOW_TRANSMIT(BooleanAttribute): + """If set to VI_FALSE, it suspends transmission as if an XOFF character + has been received. If set to VI_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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_AVAIL_NUM(RangeAttribute): + """VI_ATTR_ASRL_AVAIL_NUM shows the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_BAUD(RangeAttribute): + """VI_ATTR_ASRL_BAUD is the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_BREAK_LEN(RangeAttribute): + """This controls the duration (in milliseconds) of the break signal + asserted when VI_ATTR_ASRL_END_OUT is set to VI_ASRL_END_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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_BREAK_STATE(EnumAttribute): + """If set to VI_STATE_ASSERTED, it suspends character transmission and + places the transmission line in a break state until this attribute + is reset to VI_STATE_UNASSERTED. This attribute lets you manually + control the assertion state and length of a break signal. 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_CONNECTED(BooleanAttribute): + """VI_ATTR_ASRL_CONNECTED indicates 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_CTS_STATE(EnumAttribute): + """VI_ATTR_ASRL_CTS_STATE shows the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_DATA_BITS(RangeAttribute): + """VI_ATTR_ASRL_DATA_BITS is the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_DCD_STATE(EnumAttribute): + """VI_ATTR_ASRL_DCD_STATE represents the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_DISCARD_NULL(BooleanAttribute): + """If set to VI_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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_DSR_STATE(EnumAttribute): + """VI_ATTR_ASRL_DSR_STATE shows the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_DTR_STATE(EnumAttribute): + """VI_ATTR_ASRL_DTR_STATE shows the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_END_IN(EnumAttribute): + """VI_ATTR_ASRL_END_IN indicates the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_END_OUT(EnumAttribute): + """VI_ATTR_ASRL_END_OUT indicates the method used to terminate write + operations. + """ + resources = [(constants.InterfaceType.asrl, 'INSTR')] + + py_name = '' + + visa_name = 'VI_ATTR_ASRL_END_OUT' + + visa_type = 'ViUInt16' + + default = constants.SerialTermination.none + + read, write, local = True, True, True + + enum_type = constants.SerialTermination + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_FLOW_CNTRL(RangeAttribute): + """VI_ATTR_ASRL_FLOW_CNTRL indicates 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 + + min_value, max_value, values = 0, 65535, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_PARITY(EnumAttribute): + """VI_ATTR_ASRL_PARITY is the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_REPLACE_CHAR(RangeAttribute): + """VI_ATTR_ASRL_REPLACE_CHAR specifies the character to be used to + replace incoming characters that arrive with errors (such as + 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 + + min_value, max_value, values = 0, 0xFF, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_RI_STATE(EnumAttribute): + """VI_ATTR_ASRL_RI_STATE represents the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_RTS_STATE(EnumAttribute): + """VI_ATTR_ASRL_RTS_STATE is used to 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_STOP_BITS(EnumAttribute): + """VI_ATTR_ASRL_STOP_BITS is the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_WIRE_MODE(RangeAttribute): + """ + + """ + 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 + + min_value, max_value, values = -32768, 32767, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_XOFF_CHAR(RangeAttribute): + """VI_ATTR_ASRL_XOFF_CHAR specifies the value of the 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 + + min_value, max_value, values = 0, 0xFF, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_ASRL_XON_CHAR(RangeAttribute): + """VI_ATTR_ASRL_XON_CHAR specifies the value of the 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 + + min_value, max_value, values = 0, 0xFF, [] + + +# Could not generate class for VI_ATTR_BUFFER.html +# Exception: +""" +'list' object has no attribute 'startswith' +""" + + +# noinspection PyPep8Naming +class AttrVI_ATTR_CMDR_LA(RangeAttribute): + """VI_ATTR_CMDR_LA is the unique logical address of the commander of the + VXI device used by the given session. + """ + 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] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_DEST_ACCESS_PRIV(RangeAttribute): + """VI_ATTR_DEST_ACCESS_PRIV specifies the address modifier to be used in + high-level access operations, such as viOutXX() and viMoveOutXX(), + when writing to the destination. + """ + 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_DEST_BYTE_ORDER(RangeAttribute): + """VI_ATTR_DEST_BYTE_ORDER specifies the byte order to be used in high- + level access operations, such as viOutXX() and viMoveOutXX(), when + writing to the destination. + """ + 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 + + min_value, max_value, values = 0, 65535, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_DEST_INCREMENT(RangeAttribute): + """VI_ATTR_DEST_INCREMENT is used in the viMoveOutXX() operations to + specify by how many elements the destination offset is to be + incremented after every 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_DEV_STATUS_BYTE(RangeAttribute): + """This attribute specifies the 488-style status byte of the local + controller or device associated with 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 + + min_value, max_value, values = 0, 0xFF, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_DMA_ALLOW_EN(BooleanAttribute): + """This attribute specifies whether I/O accesses should use DMA (VI_TRUE) + or Programmed I/O (VI_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. + """ + resources = [(constants.InterfaceType.gpib, 'INSTR'), + (constants.InterfaceType.gpib, 'INTFC'), + (constants.InterfaceType.pxi, 'INSTR'), + (constants.InterfaceType.asrl, 'INSTR'), + (constants.InterfaceType.tcpip, 'INSTR'), + (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 + + +# Could not generate class for VI_ATTR_EVENT_TYPE.html +# Exception: +""" +Unknown type: ViEventType. Range: [u'0h to FFFFFFFFh'] +""" + + +# noinspection PyPep8Naming +class AttrVI_ATTR_FDC_CHNL(RangeAttribute): + """VI_ATTR_FDC_CHNL determines which Fast Data Channel (FDC) will be used + 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_FDC_MODE(RangeAttribute): + """VI_ATTR_FDC_MODE specifies 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_FDC_USE_PAIR(BooleanAttribute): + """Setting VI_ATTR_FDC_USE_PAIR to VI_TRUE specifies to use a channel + pair for transferring data. Otherwise, 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_FILE_APPEND_EN(BooleanAttribute): + """This attribute specifies whether viReadToFile() will 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_ADDR_STATE(EnumAttribute): + """This attribute shows whether the specified GPIB interface is currently + addressed to talk or listen, or is 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_ATN_STATE(EnumAttribute): + """This attribute shows the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_CIC_STATE(BooleanAttribute): + """This attribute shows whether the specified GPIB interface is 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_HS488_CBL_LEN(RangeAttribute): + """This attribute specifies the 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 = -32768, 32767, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_NDAC_STATE(EnumAttribute): + """This attribute shows the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_PRIMARY_ADDR(RangeAttribute): + """VI_ATTR_GPIB_PRIMARY_ADDR specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_READDR_EN(BooleanAttribute): + """VI_ATTR_GPIB_READDR_EN specifies whether to use repeat addressing + before each read or 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_REN_STATE(EnumAttribute): + """VI_ATTR_GPIB_REN_STATE returns the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_SECONDARY_ADDR(RangeAttribute): + """VI_ATTR_GPIB_SECONDARY_ADDR specifies the 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] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_SRQ_STATE(EnumAttribute): + """This attribute shows the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_SYS_CNTRL_STATE(BooleanAttribute): + """This attribute shows whether the specified GPIB interface is 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_GPIB_UNADDR_EN(BooleanAttribute): + """VI_ATTR_GPIB_UNADDR_EN specifies whether to unaddress the device (UNT + and UNL) after each read or 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_IMMEDIATE_SERV(BooleanAttribute): + """VI_ATTR_IMMEDIATE_SERV specifies whether the device associated with + this session is 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_INTF_INST_NAME(Attribute): + """VI_ATTR_INTF_INST_NAME specifies 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 + + # [u'N/A'] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_INTF_NUM(RangeAttribute): + """VI_ATTR_INTF_NUM specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_INTF_TYPE(RangeAttribute): + """VI_ATTR_INTF_TYPE specifies the interface type of the given session. + """ + resources = AllSessionTypes + + py_name = '' + + visa_name = 'VI_ATTR_INTF_TYPE' + + visa_type = 'ViUInt16' + + default = NotAvailable + + read, write, local = True, False, False + + min_value, max_value, values = 0, 65535, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_IO_PROT(RangeAttribute): + """VI_ATTR_IO_PROT specifies which 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. + """ + resources = [(constants.InterfaceType.gpib, 'INTFC'), + (constants.InterfaceType.gpib, 'INSTR'), + (constants.InterfaceType.asrl, '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.VI_PROT_NORMAL + + read, write, local = True, True, True + + min_value, max_value, values = 0, 65535, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_MAINFRAME_LA(RangeAttribute): + """VI_ATTR_MA.infRAME_LA specifies the 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] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_MANF_ID(RangeAttribute): + """VI_ATTR_MANF_ID is the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_MANF_NAME(Attribute): + """This string attribute is the 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 + + # [u'N/A'] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_MAX_QUEUE_LENGTH(RangeAttribute): + """VI_ATTR_MAX_QUEUE_LENGTH specifies the 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, [] + + +# Could not generate class for VI_ATTR_MEM_BASE.html +# Exception: +""" +Unknown type: VI_ATTR_MEM_BASE: +ViBusAddress +VI_ATTR_MEM_BASE_32: +ViUInt32 +VI_ATTR_MEM_BASE_64: +ViUInt64. Range: [u'VI_ATTR_MEM_BASE:', u'0h to FFFFFFFFh for 32\u2011bit applications', u'0h to FFFFFFFFFFFFFFFFh for 64\u2011bit applications', u'VI_ATTR_MEM_BASE_32:', u'0h to FFFFFFFFh', u'VI_ATTR_MEM_BASE_64:', u'0h to FFFFFFFFFFFFFFFFh'] +""" + + +# Could not generate class for VI_ATTR_MEM_SIZE.html +# Exception: +""" +Unknown type: VI_ATTR_MEM_SIZE: +ViBusSize +VI_ATTR_MEM_SIZE_32: +ViUInt32 +VI_ATTR_MEM_SIZE_64: +ViUInt64. Range: [u'VI_ATTR_MEM_SIZE:', u'0h to FFFFFFFFh for 32\u2011bit applications', u'0h to FFFFFFFFFFFFFFFFh for 64\u2011bit applications', u'VI_ATTR_MEM_SIZE_32:', u'0h to FFFFFFFFh', u'VI_ATTR_MEM_SIZE_64:', u'0h to FFFFFFFFFFFFFFFFh'] +""" + + +# noinspection PyPep8Naming +class AttrVI_ATTR_MEM_SPACE(RangeAttribute): + """VI_ATTR_MEM_SPACE specifies the VXIbus address space used by the + device. The three types are A16, A24, or A32 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 + + min_value, max_value, values = 0, 65535, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_MODEL_CODE(RangeAttribute): + """VI_ATTR_MODEL_CODE specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_MODEL_NAME(Attribute): + """This string attribute is the 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 + + # [u'N/A'] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_ACTUAL_LWIDTH(ValuesAttribute): + """VI_ATTR_PXI_ACTUAL_LWIDTH specifies the PCI Express link width + negotiated between the PCI Express 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] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_BUS_NUM(RangeAttribute): + """VI_ATTR_PXI_BUS_NUM specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_CHASSIS(RangeAttribute): + """VI_ATTR_PXI_CHASSIS specifies the 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] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_DEST_TRIG_BUS(RangeAttribute): + """VI_ATTR_PXI_DEST_TRIG_BUS specifies 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 = -32768, 32767, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_DEV_NUM(RangeAttribute): + """This is the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_DSTAR_BUS(RangeAttribute): + """VI_ATTR_PXI_DSTAR_BUS specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_DSTAR_SET(RangeAttribute): + """ + + """ + 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] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_FUNC_NUM(RangeAttribute): + """This is the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_IS_EXPRESS(BooleanAttribute): + """VI_ATTR_PXI_IS_EXPRESS specifies 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_MAX_LWIDTH(ValuesAttribute): + """VI_ATTR_PXI_MAX_LWIDTH specifies the 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] + + +# noinspection PyPep8Naming +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 VI_PXI_ADDR_NONE, + the value of this attribute is meaningless for the given PXI + device. + """ + resources = [(constants.InterfaceType.pxi, 'INSTR')] + + py_name = '' + + visa_name = 'VI_ATTR_PXI_MEM_BASE_BARX' + + visa_type = 'ViUInt32' + + default = NotAvailable + + read, write, local = True, False, False + + min_value, max_value, values = 0, 0xFFFFFFFF, [] + + +# noinspection PyPep8Naming +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 VI_PXI_ADDR_NONE, + the value of this attribute is meaningless for the given PXI + device. + """ + resources = [(constants.InterfaceType.pxi, 'INSTR')] + + py_name = '' + + visa_name = 'VI_ATTR_PXI_MEM_SIZE_BARX' + + visa_type = 'ViUInt32' + + default = NotAvailable + + read, write, local = True, False, False + + min_value, max_value, values = 0, 0xFFFFFFFF, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_MEM_TYPE_BARX(RangeAttribute): + """Memory type used by the device in the specified BAR (if applicable). + """ + resources = [(constants.InterfaceType.pxi, 'INSTR')] + + py_name = '' + + visa_name = 'VI_ATTR_PXI_MEM_TYPE_BARX' + + visa_type = 'ViUInt16' + + default = NotAvailable + + read, write, local = True, False, False + + min_value, max_value, values = 0, 65535, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_SLOT_LBUS_LEFT(RangeAttribute): + """VI_ATTR_PXI_SLOT_LBUS_LEFT specifies the slot number or special + feature connected to the local bus left lines of this device. + """ + 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] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_SLOT_LBUS_RIGHT(RangeAttribute): + """VI_ATTR_PXI_SLOT_LBUS_RIGHT specifies the slot number or special + feature connected to the local bus right lines of this device. + """ + 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] + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_SLOT_LWIDTH(ValuesAttribute): + """VI_ATTR_PXI_SLOT_LWIDTH specifies the PCI Express link width of the + PXI Express peripheral slot in which the device resides. 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] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_SLOTPATH(Attribute): + """VI_ATTR_PXI_SLOTPATH specifies the 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 + + # [u'N/A'] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_SRC_TRIG_BUS(RangeAttribute): + """VI_ATTR_PXI_SRC_TRIG_BUS specifies the 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 = -32768, 32767, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_STAR_TRIG_BUS(RangeAttribute): + """VI_ATTR_PXI_STAR_TRIG_BUS specifies 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 = -32768, 32767, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_STAR_TRIG_LINE(RangeAttribute): + """VI_ATTR_PXI_STAR_TRIG_LINE specifies 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 = -32768, 32767, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_PXI_TRIG_BUS(RangeAttribute): + """VI_ATTR_PXI_TRIG_BUS specifies 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 = -32768, 32767, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_RD_BUF_OPER_MODE(RangeAttribute): + """VI_ATTR_RD_BUF_OPER_MODE specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_RD_BUF_SIZE(RangeAttribute): + """This is the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_RM_SESSION(RangeAttribute): + """This is the current size of the formatted I/O input buffer for this + session. The user can modify this value by calling viSetBuf(). + + Not implemented as resource property, use .resource_manager.session + """ + resources = AllSessionTypes + + # See docstring + py_name = '' + + visa_name = 'VI_ATTR_RM_SESSION' + + visa_type = 'ViUInt32' + + default = NotAvailable + + read, write, local = True, False, True + + min_value, max_value, values = 0, 4294967295, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_RSRC_CLASS(Attribute): + """VI_ATTR_RSRC_CLASS specifies the resource class (for example, "INSTR") + as defined by the canonical resource name. + """ + resources = AllSessionTypes + + py_name = 'resource_class' + + visa_name = 'VI_ATTR_RSRC_CLASS' + + visa_type = 'ViString' + + default = NotAvailable + + read, write, local = True, False, False + + # [u'N/A'] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_RSRC_IMPL_VERSION(RangeAttribute): + """VI_ATTR_RSRC_IMPL_VERSION is the resource version that uniquely identifies + each of the different 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_RSRC_LOCK_STATE(EnumAttribute): + """VI_ATTR_RSRC_LOCK_STATE indicates the 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.VI_NO_LOCK + + read, write, local = True, False, False + + enum_type = constants.AccessModes + + +# noinspection PyPep8Naming +class AttrVI_ATTR_RSRC_MANF_ID(RangeAttribute): + """VI_ATTR_RSRC_MANF_ID is a value that corresponds to the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_RSRC_MANF_NAME(Attribute): + """VI_ATTR_RSRC_MANF_NAME is a string that corresponds to the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_RSRC_NAME(Attribute): + """VI_ATTR_RSRC_MANF_NAME is a string that corresponds to the 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_name' + + visa_name = 'VI_ATTR_RSRC_NAME' + + visa_type = 'ViRsrc' + + default = NotAvailable + + read, write, local = True, False, False + + +# noinspection PyPep8Naming +class AttrVI_ATTR_RSRC_SPEC_VERSION(RangeAttribute): + """VI_ATTR_RSRC_SPEC_VERSION is the resource version that uniquely identifies + the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_SEND_END_EN(BooleanAttribute): + """VI_ATTR_SEND_END_EN specifies whether to assert END during the + transfer of the last byte of the buffer. + """ + resources = [(constants.InterfaceType.gpib, 'INSTR'), + (constants.InterfaceType.gpib, 'INTFC'), + (constants.InterfaceType.asrl, 'INSTR'), + (constants.InterfaceType.tcpip, 'INSTR'), + (constants.InterfaceType.usb, 'INSTR'), + (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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_SLOT(RangeAttribute): + """VI_ATTR_SLOT specifies the physical slot location of the device. If + the slot number is not known, VI_UNKNOWN_SLOT is returned. + """ + 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 + + # [u'VXI', u'0 to 12', u'VI_UNKNOWN_SLOT (\u20131)', u'PXI', u'1 to 18', u'VI_UNKNOWN_SLOT (\u20131)'], ValueError('too many values to unpack',) + + +# noinspection PyPep8Naming +class AttrVI_ATTR_SRC_ACCESS_PRIV(RangeAttribute): + """VI_ATTR_SRC_ACCESS_PRIV specifies the address modifier to be used in + high-level access operations, such as viInXX() and viMoveInXX(), + when reading from the source. + """ + 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 + + min_value, max_value, values = 0, 65535, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_SRC_BYTE_ORDER(RangeAttribute): + """VI_ATTR_SRC_BYTE_ORDER specifies the byte order to be used in high- + level access operations, such as viInXX() and viMoveInXX(), when + reading from the source. + """ + 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 + + min_value, max_value, values = 0, 65535, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_SRC_INCREMENT(RangeAttribute): + """VI_ATTR_SRC_INCREMENT is used in the viMoveInXX() operations to + specify by how many elements the source offset is to be + incremented after every 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_SUPPRESS_END_EN(BooleanAttribute): + """VI_ATTR_SUPPRESS_END_EN is relevant only in viRead and related + operations. + """ + resources = [(constants.InterfaceType.asrl, 'INSTR'), + (constants.InterfaceType.tcpip, 'SOCKET'), + (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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_TCPIP_ADDR(Attribute): + """This is the 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 + + # [u'N/A'] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_TCPIP_DEVICE_NAME(Attribute): + """This specifies the 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 + + # [u'N/A'] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_TCPIP_HOSTNAME(Attribute): + """This specifies the 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 + + # [u'N/A'] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_TCPIP_KEEPALIVE(BooleanAttribute): + """Setting this attribute to TRUE requests that a TCP/IP provider enable + the use of keep-alive packets on TCP connections. 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 + + +# noinspection PyPep8Naming +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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_TCPIP_PORT(RangeAttribute): + """This specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_TERMCHAR(RangeAttribute): + """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. + """ + 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 + + min_value, max_value, values = 0, 0xFF, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_TERMCHAR_EN(BooleanAttribute): + """VI_ATTR_TERMCHAR_EN is a flag that determines whether the read + operation should 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). + """ + 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_TMO_VALUE(RangeAttribute): + """VI_ATTR_TMO_VALUE specifies the minimum timeout value to use (in + milliseconds) when accessing the device associated with the given + session. 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 = '' + + visa_name = 'VI_ATTR_TMO_VALUE' + + visa_type = 'ViUInt32' + + default = 2000 + + read, write, local = True, True, True + + min_value, max_value, values = 0, 0xFFFFFFFF, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_TRIG_ID(ValuesAttribute): + """VI_ATTR_TRIG_ID is the 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 + + values = [] #TODO + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_ALT_SETTING(RangeAttribute): + """VI_ATTR_USB_ALT_SETTING specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_BULK_IN_PIPE(RangeAttribute): + """VI_ATTR_USB_BULK_IN_PIPE specifies the 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] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_BULK_IN_STATUS(RangeAttribute): + """VI_ATTR_USB_BULK_IN_STATUS specifies whether 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_BULK_OUT_PIPE(RangeAttribute): + """VI_ATTR_USB_BULK_OUT_PIPE specifies the endpoint address of the USB + bulk-out or interrupt-out pipe used by the given session. 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] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_BULK_OUT_STATUS(RangeAttribute): + """VI_ATTR_USB_BULK_OUT_STATUS specifies whether the USB bulk-out or + interrupt-out 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_OUT_STATUS' + + visa_type = 'ViInt16' + + default = NotAvailable + + read, write, local = True, True, True + + min_value, max_value, values = -32768, 32767, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_CLASS(RangeAttribute): + """VI_ATTR_USB_CLASS specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_CTRL_PIPE(RangeAttribute): + """VI_ATTR_USB_CTRL_PIPE specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_END_IN(ValuesAttribute): + """VI_ATTR_USB_END_IN indicates the 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 + + values = [constants.VI_USB_END_NONE, + constants.VI_USB_END_SHORT, + constants.VI_USB_END_SHORT_OR_COUNT] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_INTFC_NUM(RangeAttribute): + """VI_ATTR_USB_INTFC_NUM specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_INTR_IN_PIPE(RangeAttribute): + """VI_ATTR_USB_INTR_IN_PIPE specifies the 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] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_INTR_IN_STATUS(RangeAttribute): + """VI_ATTR_USB_INTR_IN_STATUS specifies 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_MAX_INTR_SIZE(RangeAttribute): + """VI_ATTR_USB_MAX_INTR_SIZE specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_NUM_INTFCS(RangeAttribute): + """VI_ATTR_USB_NUM_INTFCS specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_NUM_PIPES(RangeAttribute): + """VI_ATTR_USB_NUM_PIPES specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_PROTOCOL(RangeAttribute): + """VI_ATTR_USB_PROTOCOL specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_SERIAL_NUM(Attribute): + """VI_ATTR_USB_SERIAL_NUM specifies the 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 + + # [u'N/A'] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_USB_SUBCLASS(RangeAttribute): + """VI_ATTR_USB_SUBCLASS specifies the 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, [] + + +# Could not generate class for VI_ATTR_USER_DATA.html +# Exception: +""" +Unknown type: VI_ATTR_USER_DATA: +ViAddr +VI_ATTR_USER_DATA_32: +ViUInt32 +VI_ATTR_USER_DATA_64: +ViUInt64. Range: [u'VI_ATTR_USER_DATA:', u'Not specified', u'VI_ATTR_USER_DATA_32:', u'0h to FFFFFFFFh', u'VI_ATTR_USER_DATA_64:', u'0h to FFFFFFFFFFFFFFFFh'] +""" + + +# noinspection PyPep8Naming +class AttrVI_ATTR_VXI_DEV_CLASS(RangeAttribute): + """This attribute represents the VXI-defined device class to which the + resource belongs, either message based (VI_VXI_CLASS_MESSAGE), + register based (VI_VXI_CLASS_REGISTER), extended + (VI_VXI_CLASS_EXTENDED), or memory (VI_VXI_CLASS_MEMORY). 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 + + min_value, max_value, values = 0, 65535, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_VXI_LA(RangeAttribute): + """For an INSTR session, VI_ATTR_VXI_LA specifies the logical address of + the VXI or VME device used by the given session. 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_VXI_TRIG_DIR(RangeAttribute): + """VI_ATTR_TRIG_DIR is a 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_VXI_TRIG_LINES_EN(RangeAttribute): + """VI_ATTR_VXI_TRIG_LINES_EN is a 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_VXI_TRIG_STATUS(RangeAttribute): + """This attribute shows the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_VXI_TRIG_SUPPORT(RangeAttribute): + """This attribute shows which VXI trigger lines this implementation + supports. This is a bit vector with bits 0-9 corresponding to + VI_TRIG_TTL0 through VI_TRIG_ECL1. + """ + 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_VXI_VME_INTR_STATUS(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_VXI_VME_INTR_STATUS' + + visa_type = 'ViUInt16' + + default = NotAvailable + + read, write, local = True, False, False + + min_value, max_value, values = 0, 65535, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_VXI_VME_SYSFAIL_STATE(EnumAttribute): + """This attribute shows the 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 + + +# noinspection PyPep8Naming +class AttrVI_ATTR_WIN_ACCESS(RangeAttribute): + """VI_ATTR_WIN_ACCESS specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_WIN_ACCESS_PRIV(RangeAttribute): + """VI_ATTR_WIN_ACCESS_PRIV specifies the address modifier to be used in + low-level access operations, such as 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 + + min_value, max_value, values = 0, 65535, [] + + +# Could not generate class for VI_ATTR_WIN_BASE_ADDR.html +# Exception: +""" +Unknown type: VI_ATTR_WIN_BASE_ADDR: +ViBusAddress +VI_ATTR_WIN_BASE_ADDR_32: +ViUInt32 +VI_ATTR_WIN_BASE_ADDR_64: +ViUInt64. Range: [u'VI_ATTR_WIN_BASE_ADDR:', u'0h to FFFFFFFFh for 32\u2011bit applications', u'0h to FFFFFFFFFFFFFFFFh for 64\u2011bit applications', u'VI_ATTR_WIN_BASE_ADDR_32:', u'0h to FFFFFFFFh', u'VI_ATTR_WIN_BASE_ADDR_64:', u'0h to FFFFFFFFFFFFFFFFh'] +""" + + +# noinspection PyPep8Naming +class AttrVI_ATTR_WIN_BYTE_ORDER(RangeAttribute): + """VI_ATTR_WIN_BYTE_ORDER specifies the byte order to be used in low- + level access operations, such as 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 + + min_value, max_value, values = 0, 65535, [] + + +# Could not generate class for VI_ATTR_WIN_SIZE.html +# Exception: +""" +Unknown type: VI_ATTR_WIN_SIZE: +ViBusSize +VI_ATTR_WIN_SIZE_32: +ViUInt32 +VI_ATTR_WIN_SIZE_64: +ViUInt64. Range: [u'VI_ATTR_WIN_SIZE:', u'0h to FFFFFFFFh for 32\u2011bit applications', u'0h to FFFFFFFFFFFFFFFFh for 64\u2011bit applications', u'VI_ATTR_WIN_SIZE_32:', u'0h to FFFFFFFFh', u'VI_ATTR_WIN_SIZE_64:', u'0h to FFFFFFFFFFFFFFFFh'] +""" + + +# noinspection PyPep8Naming +class AttrVI_ATTR_WR_BUF_OPER_MODE(RangeAttribute): + """VI_ATTR_WR_BUF_OPER_MODE specifies the 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, [] + + +# noinspection PyPep8Naming +class AttrVI_ATTR_WR_BUF_SIZE(RangeAttribute): + """This is the 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, [] + diff --git a/pyvisa/compat/__init__.py b/pyvisa/compat/__init__.py new file mode 100644 index 0000000..abd0f78 --- /dev/null +++ b/pyvisa/compat/__init__.py @@ -0,0 +1,144 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.compat + ~~~~~~~~~~~~~ + + Compatibility layer. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +""" + +from __future__ import (division, unicode_literals, print_function, + absolute_import) + +import sys + + +PYTHON3 = sys.version >= '3' + +if PYTHON3: + string_types = str + + def u(x): + return x + + integer_types = (int, ) + + input = input + + int_to_bytes = int.to_bytes + int_from_bytes = int.from_bytes + +else: + string_types = basestring + + import codecs + + def u(x): + return codecs.unicode_escape_decode(x)[0] + + integer_types = (int, long) + + input = raw_input + + # The 2 following function implementation extracted from the python-future + # project + import collections + + def int_to_bytes(integer, length, byteorder, signed=False): + """ + Return an array of bytes representing an integer. + The integer is represented using length bytes. An OverflowError is + raised if the integer is not representable with the given number of + bytes. + The byteorder argument determines the byte order used to represent the + integer. If byteorder is 'big', the most significant byte is at the + beginning of the byte array. If byteorder is 'little', the most + significant byte is at the end of the byte array. To request the + native byte order of the host system, use `sys.byteorder' as the byte + order value. + The signed keyword-only argument determines whether two's complement is + used to represent the integer. If signed is False and a negative + integer is given, an OverflowError is raised. + """ + if length < 0: + raise ValueError("length argument must be non-negative") + if length == 0 and integer == 0: + return bytes() + if signed and integer < 0: + bits = length * 8 + num = (2**bits) + integer + if num <= 0: + raise OverflowError("int too smal to convert") + else: + if integer < 0: + raise OverflowError("can't convert negative int to unsigned") + num = integer + if byteorder not in ('little', 'big'): + raise ValueError("byteorder must be either 'little' or 'big'") + h = b'%x' % num + s = bytes((b'0'*(len(h) % 2) + h).zfill(length*2).decode('hex')) + if signed: + high_set = s[0] & 0x80 + if integer > 0 and high_set: + raise OverflowError("int too big to convert") + if integer < 0 and not high_set: + raise OverflowError("int too small to convert") + if len(s) > length: + raise OverflowError("int too big to convert") + return s if byteorder == 'big' else s[::-1] + + def int_from_bytes(mybytes, byteorder='big', signed=False): + """ + Return the integer represented by the given array of bytes. + The mybytes argument must either support the buffer protocol or be an + iterable object producing bytes. Bytes and bytearray are examples of + built-in objects that support the buffer protocol. + The byteorder argument determines the byte order used to represent the + integer. If byteorder is 'big', the most significant byte is at the + beginning of the byte array. If byteorder is 'little', the most + significant byte is at the end of the byte array. To request the + native byte order of the host system, use `sys.byteorder' as the byte + order value. + The signed keyword-only argument indicates whether two's complement is + used to represent the integer. + """ + if byteorder not in ('little', 'big'): + raise ValueError("byteorder must be either 'little' or 'big'") + if isinstance(mybytes, unicode): + raise TypeError("cannot convert unicode objects to bytes") + # mybytes can also be passed as a sequence of integers on Py3. + # Test for this: + elif isinstance(mybytes, collections.Iterable): + mybytes = bytes(mybytes) + b = mybytes if byteorder == 'big' else mybytes[::-1] + if len(b) == 0: + b = b'\x00' + # The encode() method has been disabled by newbytes, but Py2's + # str has it: + num = int(b.encode('hex'), 16) + if signed and (b[0] & 0x80): + num = num - (2 ** (len(b)*8)) + return num + +try: + from collections import OrderedDict +except ImportError: + from .ordereddict import OrderedDict + +try: + from logging import NullHandler +except ImportError: + from .nullhandler import NullHandler + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(meta): + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, str('temporary_class'), (), {}) diff --git a/pyvisa/compat/nullhandler.py b/pyvisa/compat/nullhandler.py new file mode 100644 index 0000000..e1ff509 --- /dev/null +++ b/pyvisa/compat/nullhandler.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.compat.nullhandler + ~~~~~~~~~~~~~~~~~~~~~~~~~ + + Taken from the Python 2.7 source code. + + :copyright: 2013, PSF + :license: PSF License +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import logging + + +class NullHandler(logging.Handler): + """ + This handler does nothing. It's intended to be used to avoid the + "No handlers could be found for logger XXX" one-off warning. This is + important for library code, which may contain code to log events. If a user + of the library does not configure logging, the one-off warning might be + produced; to avoid this, the library developer simply needs to instantiate + a NullHandler and add it to the top-level logger of the library module or + package. + """ + def handle(self, record): + pass + + def emit(self, record): + pass + + def createLock(self): + # noinspection PyAttributeOutsideInit + self.lock = None diff --git a/pyvisa/compat/ordereddict.py b/pyvisa/compat/ordereddict.py new file mode 100644 index 0000000..5b0303f --- /dev/null +++ b/pyvisa/compat/ordereddict.py @@ -0,0 +1,127 @@ +# Copyright (c) 2009 Raymond Hettinger +# +# 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 UserDict import DictMixin + +class OrderedDict(dict, DictMixin): + + def __init__(self, *args, **kwds): + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + try: + self.__end + except AttributeError: + self.clear() + self.update(*args, **kwds) + + def clear(self): + self.__end = end = [] + end += [None, end, end] # sentinel node for doubly linked list + self.__map = {} # key --> [key, prev, next] + dict.clear(self) + + def __setitem__(self, key, value): + if key not in self: + end = self.__end + curr = end[1] + curr[2] = end[1] = self.__map[key] = [key, curr, end] + dict.__setitem__(self, key, value) + + def __delitem__(self, key): + dict.__delitem__(self, key) + key, prev, next = self.__map.pop(key) + prev[2] = next + next[1] = prev + + def __iter__(self): + end = self.__end + curr = end[2] + while curr is not end: + yield curr[0] + curr = curr[2] + + def __reversed__(self): + end = self.__end + curr = end[1] + while curr is not end: + yield curr[0] + curr = curr[1] + + def popitem(self, last=True): + if not self: + raise KeyError('dictionary is empty') + if last: + key = reversed(self).next() + else: + key = iter(self).next() + value = self.pop(key) + return key, value + + def __reduce__(self): + items = [[k, self[k]] for k in self] + tmp = self.__map, self.__end + del self.__map, self.__end + inst_dict = vars(self).copy() + self.__map, self.__end = tmp + if inst_dict: + return (self.__class__, (items,), inst_dict) + return self.__class__, (items,) + + def keys(self): + return list(self) + + setdefault = DictMixin.setdefault + update = DictMixin.update + pop = DictMixin.pop + values = DictMixin.values + items = DictMixin.items + iterkeys = DictMixin.iterkeys + itervalues = DictMixin.itervalues + iteritems = DictMixin.iteritems + + def __repr__(self): + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, self.items()) + + def copy(self): + return self.__class__(self) + + @classmethod + def fromkeys(cls, iterable, value=None): + d = cls() + for key in iterable: + d[key] = value + return d + + def __eq__(self, other): + if isinstance(other, OrderedDict): + if len(self) != len(other): + return False + for p, q in zip(self.items(), other.items()): + if p != q: + return False + return True + return dict.__eq__(self, other) + + def __ne__(self, other): + return not self == other diff --git a/pyvisa/compat/struct.py b/pyvisa/compat/struct.py new file mode 100644 index 0000000..2d0e429 --- /dev/null +++ b/pyvisa/compat/struct.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.compat.struct + ~~~~~~~~~~~~~~~~~~~~~~~~~ + + Python 2/3 compatibility for struct module + + :copyright: 2015, PSF + :license: PSF License +""" + +from __future__ import (division, unicode_literals, print_function, + absolute_import) + +import sys +import struct + +# we always want the exception to be able to catch it +error = struct.error + +# compatibility for unicode literals was introduced in 2.7.8 +# if we're above that there is nothing to do except aliasing +if sys.hexversion >= 0x02070800: + pack = struct.pack + pack_into = struct.pack_into + unpack = struct.unpack + unpack_from = struct.unpack_from + calcsize = struct.calcsize +else: + def pack(fmt, *args): + return struct.pack(str(fmt), *args) + + def pack_into(fmt, *args, **argk): + return struct.pack_into(str(fmt), *args, **argk) + + def unpack(fmt, string): + return struct.unpack(str(fmt), string) + + def unpack_from(fmt, *args, **kwargs): + return struct.unpack_from(str(fmt), *args, **kwargs) + + def calcsize(fmt): + return struct.calcsize(str(fmt)) diff --git a/pyvisa/constants.py b/pyvisa/constants.py new file mode 100644 index 0000000..c2e907f --- /dev/null +++ b/pyvisa/constants.py @@ -0,0 +1,1060 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.constants + ~~~~~~~~~~~~~~~~ + + 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 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import enum + +from .compat import PYTHON3 + +if PYTHON3: + LongEnum = enum.IntEnum +else: + class LongEnum(long, enum.Enum): + pass + +# _to_int() 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. +# + + +def _to_int(x): + """Converts a completion and error code as it is listed in 32-bit notation + in the VPP-4.3.2 specification to the actual integer value. + """ + if x > 0x7FFFFFFF: + return int(x - 0x100000000) + else: + return int(x) + +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) + +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) + +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 = 0x3FFF0007 +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 + +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 = 0x3FFF0098 +VI_ATTR_WIN_SIZE = 0x3FFF009A +VI_ATTR_ASRL_AVAIL_NUM = 0x3FFF00AC +VI_ATTR_MEM_BASE = 0x3FFF00AD +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 = 0x3FFF00DD +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_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_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 = 0x3FFF4026 +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_USB_RECV_INTR_SIZE = 0x3FFF41B0 +VI_ATTR_USB_RECV_INTR_DATA = 0xBFFF41B1 + + +VI_ATTR_VXI_TRIG_DIR = _to_int(0x3FFF4044) +VI_ATTR_VXI_TRIG_LINES_EN = _to_int(0x3FFF4043) + +# +# 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 + + +# +# 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_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_ECL0 = 8 +VI_TRIG_ECL1 = 9 +VI_TRIG_PANEL_IN = 27 +VI_TRIG_PANEL_OUT = 28 + +VI_TRIG_PROT_DEFAULT = 0 +VI_TRIG_PROT_ON = 1 +VI_TRIG_PROT_OFF = 2 +VI_TRIG_PROT_SYNC = 5 + +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 + +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_WIDTH_8 = 1 +VI_WIDTH_16 = 2 +VI_WIDTH_32 = 4 + +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_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_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 = _to_int(0x3FFF0221) +VI_ATTR_PXI_MEM_BASE_BAR1 = _to_int(0x3FFF0222) +VI_ATTR_PXI_MEM_BASE_BAR2 = _to_int(0x3FFF0223) +VI_ATTR_PXI_MEM_BASE_BAR3 = _to_int(0x3FFF0224) +VI_ATTR_PXI_MEM_BASE_BAR4 = _to_int(0x3FFF0225) +VI_ATTR_PXI_MEM_BASE_BAR5 = _to_int(0x3FFF0226) +VI_ATTR_PXI_MEM_SIZE_BAR0 = _to_int(0x3FFF0231) +VI_ATTR_PXI_MEM_SIZE_BAR1 = _to_int(0x3FFF0232) +VI_ATTR_PXI_MEM_SIZE_BAR2 = _to_int(0x3FFF0233) +VI_ATTR_PXI_MEM_SIZE_BAR3 = _to_int(0x3FFF0234) +VI_ATTR_PXI_MEM_SIZE_BAR4 = _to_int(0x3FFF0235) +VI_ATTR_PXI_MEM_SIZE_BAR5 = _to_int(0x3FFF0236) +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) + +# TODO: What is the value +VI_ATTR_PXI_MEM_BASE_BARX = None +VI_ATTR_PXI_MEM_SIZE_BARX = None +VI_ATTR_PXI_MEM_TYPE_BARX = None + + +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_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 + + +# Enums + +class AccessModes(enum.IntEnum): + + #: Does not obtain any lock on the VISA resource. + no_lock = 0 + + #: Obtains a exclusive lock on the VISA resource. + exclusive_lock = 1 + + #: Obtains a lock on the VISA resouce which may be shared + #: between multiple VISA sessions. + shared_lock = 2 + + +class StopBits(enum.IntEnum): + """The number of stop bits that indicate the end of a frame. + """ + one = VI_ASRL_STOP_ONE + one_and_a_half = VI_ASRL_STOP_ONE5 + two = VI_ASRL_STOP_TWO + + +class Parity(enum.IntEnum): + """The parity types to use with every frame transmitted and received on a serial session. + """ + 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 + + +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 + + +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 + + +class AddressState(enum.IntEnum): + + unaddressed = VI_GPIB_UNADDRESSED + talker = VI_GPIB_TALKER + listenr = VI_GPIB_LISTENER + + +class IOProtocol(enum.IntEnum): + + 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 + + +class LineState(enum.IntEnum): + + asserted = VI_STATE_ASSERTED + unasserted = VI_STATE_UNASSERTED + unknown = VI_STATE_UNKNOWN + + +class EventMechanism(enum.IntEnum): + """The available event mechanisms for event handling. + """ + + queue = VI_QUEUE + handler = VI_HNDLR + + #: events queued but handler not called + suspend_handler = VI_SUSPEND_HNDLR + + all = VI_ALL_MECH + + +# Note that enum.IntEnum fails here for python2: +# OverflowError: Python int too large to convert to C long +# so use LongEnum instead (some values are too large, and ViEventType is unsigned) +class EventType(LongEnum): + """The available event types for event handling. + """ + + io_completion = VI_EVENT_IO_COMPLETION + trig = VI_EVENT_TRIG + service_request = VI_EVENT_SERVICE_REQ + clear = VI_EVENT_CLEAR + exception = VI_EVENT_EXCEPTION + gpib_controller_in_charge = VI_EVENT_GPIB_CIC + gpib_talk = VI_EVENT_GPIB_TALK + gpib_listen = VI_EVENT_GPIB_LISTEN + vxi_vme_sysfail = VI_EVENT_VXI_VME_SYSFAIL + vxi_vme_sysreset = VI_EVENT_VXI_VME_SYSRESET + vxi_signal_interrupt = VI_EVENT_VXI_SIGP + vxi_vme_interrupt = VI_EVENT_VXI_VME_INTR + pxi_interrupt = VI_EVENT_PXI_INTR + tcpip_connect = VI_EVENT_TCPIP_CONNECT + usb_interrupt = VI_EVENT_USB_INTR + all_enabled = VI_ALL_ENABLED_EVENTS + + +class StatusCode(enum.IntEnum): + """Specifies the status codes that NI-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_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_syncronous = 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 diff --git a/pyvisa/ctwrapper/__init__.py b/pyvisa/ctwrapper/__init__.py new file mode 100644 index 0000000..631df6e --- /dev/null +++ b/pyvisa/ctwrapper/__init__.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.ctwrapper + ~~~~~~~~~~~~~~~~ + + ctypes wrapper for NI-VISA library. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +from .highlevel import NIVisaLibrary + +WRAPPER_CLASS = NIVisaLibrary + diff --git a/pyvisa/ctwrapper/cthelper.py b/pyvisa/ctwrapper/cthelper.py new file mode 100644 index 0000000..3599c02 --- /dev/null +++ b/pyvisa/ctwrapper/cthelper.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.ctwrapper._ct + ~~~~~~~~~~~~~~~~~~~~ + + Cross platform helper of ctypes. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +# ctypes and os shouldn't be re-exported. +import os as _os +import sys as _sys + +import ctypes as _ctypes + +PYTHON3 = _sys.version_info >= (3, 0) + +if _os.name == 'nt': + 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. +# noinspection PyUnresolvedReferences +if _os.name == "posix" and _sys.platform.startswith('linux'): + + # Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump + def define_find_libary(): + import re + import tempfile + import errno + + 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): + # XXX assuming GLIBC's ldconfig (with option -p) + expr = r'/[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name) + res = re.search(expr, + _os.popen('/sbin/ldconfig -p 2>/dev/null').read()) + if not res: + # Hm, this works only for libs needed by the python executable. + cmd = 'ldd %s 2>/dev/null' % _sys.executable + res = re.search(expr, _os.popen(cmd).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 diff --git a/pyvisa/ctwrapper/functions.py b/pyvisa/ctwrapper/functions.py new file mode 100644 index 0000000..472d573 --- /dev/null +++ b/pyvisa/ctwrapper/functions.py @@ -0,0 +1,1901 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.ctwrapper.functions + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Defines VPP 4.3.2 wrapping functions using ctypes, adding signatures to the library. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import warnings + +from pyvisa.highlevel import ResourceInfo +from pyvisa import attributes, constants + +from . import types +from .types import * +from ctypes import byref, c_void_p, c_double, c_long, POINTER, create_string_buffer + +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_asynchronously", "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 + + +def set_user_handle_type(library, user_handle): + """Set the type of the user handle to install and uninstall handler signature. + + :param library: the visa library wrapped by ctypes. + :param user_handle: use None for a void_p + """ + + # 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)) + + 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] + + +def set_signatures(library, errcheck=None): + """Set the signatures of most visa functions in the library. + + All instrumentation related functions are specified here. + + :param library: the visa library wrapped by ctypes. + :type library: ctypes.WinDLL or ctypes.CDLL + :param errcheck: error checking callable used for visa functions that return + ViStatus. + It should be take three areguments (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_) + # noinspection PyProtectedMember + 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, argtypes, restype, errcheck): + """Set the signature of single function in a library. + + :param library: ctypes wrapped library. + :type library: ctypes.WinDLL or ctypes.CDLL + :param function_name: name of the function as appears in the header file. + :type function_name: str + :param argtypes: a tuple of ctypes types to specify the argument types that the function accepts. + :param restype: A ctypes type to specify the result type of the foreign function. + Use None for void, a function not returning anything. + :param errcheck: a callabe + + :raises: AttributeError + """ + + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param mode: How to assert the interrupt. (Constants.ASSERT*) + :param status_id: This is the status value to be presented during an interrupt acknowledge cycle. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viAssertIntrSignal(session, mode, status_id) + + +def assert_trigger(library, session, protocol): + """Asserts software or hardware trigger. + + Corresponds to viAssertTrigger function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param protocol: Trigger protocol to use during assertion. (Constants.PROT*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viAssertTrigger(session, protocol) + + +def assert_utility_signal(library, session, line): + """Asserts or deasserts the specified utility bus signal. + + Corresponds to viAssertUtilSignal function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param line: specifies the utility bus signal to assert. (Constants.UTIL_ASSERT*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viAssertUtilSignal(session, line) + + +def buffer_read(library, session, count): + """Reads data from device or interface through the use of a formatted I/O read buffer. + + Corresponds to viBufRead function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param count: Number of bytes to be read. + :return: data read, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param data: data to be written. + :type data: bytes + :return: number of written bytes, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viClear(session) + + +def close(library, session): + """Closes the specified session, event, or find list. + + Corresponds to viClose function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session, event, or find list. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viClose(session) + + +def disable_event(library, session, event_type, mechanism): + """Disables notification of the specified event type(s) via the specified mechanism(s). + + Corresponds to viDisableEvent function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param mechanism: Specifies event handling mechanisms to be disabled. + (Constants.VI_QUEUE, .VI_HNDLR, .VI_SUSPEND_HNDLR, .VI_ALL_MECH) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viDisableEvent(session, event_type, mechanism) + + +def discard_events(library, session, event_type, mechanism): + """Discards event occurrences for specified event types and mechanisms in a session. + + Corresponds to viDiscardEvents function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param mechanism: Specifies event handling mechanisms to be dicarded. + (Constants.VI_QUEUE, .VI_HNDLR, .VI_SUSPEND_HNDLR, .VI_ALL_MECH) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param mechanism: Specifies event handling mechanisms to be enabled. + (Constants.VI_QUEUE, .VI_HNDLR, .VI_SUSPEND_HNDLR) + :param context: + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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): + """Returns the next resource from the list of resources found during a previous call to find_resources(). + + Corresponds to viFindNext function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param find_list: Describes a find list. This parameter must be created by find_resources(). + :return: Returns a string identifying the location of a device, return value of the library call. + :rtype: unicode (Py2) or str (Py3), :class:`pyvisa.constants.StatusCode` + """ + 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, query): + """Queries a VISA system to locate the resources associated with a specified interface. + + Corresponds to viFindRsrc function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session (unused, just to uniform signatures). + :param query: A regular expression followed by an optional logical expression. Use '?*' for all. + :return: find_list, return_counter, instrument_description, return value of the library call. + :rtype: ViFindList, int, unicode (Py2) or str (Py3), :class:`pyvisa.constants.StatusCode` + """ + find_list = ViFindList() + return_counter = ViUInt32() + instrument_description = create_string_buffer(constants.VI_FIND_BUFLEN) + + # [ViSession, ViString, ViPFindList, ViPUInt32, ViAChar] + # ViString converts from (str, unicode, bytes) to bytes + 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): + """Manually flushes the specified buffers associated with formatted I/O operations and/or serial communication. + + Corresponds to viFlush function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param mask: Specifies the action to be taken with flushing the buffer. + (Constants.READ*, .WRITE*, .IO*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session, event, or find list. + :param attribute: Resource attribute for which the state query is made (see Attributes.*) + :return: The state of the queried attribute for a specified resource, return value of the library call. + :rtype: unicode (Py2) or str (Py3), list or other type, :class:`pyvisa.constants.StatusCode` + """ + + # FixMe: How to deal with ViBuf? + 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 + elif datatype == ViAUInt8: + 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: + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param data: data tor write. + :type data: bytes + :return: Number of written bytes, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param mode: Specifies the state of the ATN line and optionally the local active controller state. + (Constants.GPIB_ATN*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viGpibControlATN(session, mode) + + +def gpib_control_ren(library, session, mode): + """Controls the state of the GPIB Remote Enable (REN) interface line, and optionally the remote/local + state of the device. + + Corresponds to viGpibControlREN function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param mode: Specifies the state of the REN line and optionally the device remote/local state. + (Constants.GPIB_REN*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viGpibControlREN(session, mode) + + +def gpib_pass_control(library, session, primary_address, secondary_address): + """Tell the GPIB device at the specified address to become controller in charge (CIC). + + Corresponds to viGpibPassControl function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param primary_address: Primary address of the GPIB device to which you want to pass control. + :param secondary_address: 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. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viGpibSendIFC(session) + + +def read_memory(library, session, space, offset, width, extended=False): + """Reads in an 8-bit, 16-bit, 32-bit, or 64-bit value from the specified memory space and offset. + + Corresponds to viIn* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param width: Number of bits to read. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from memory, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + if width == 8: + return in_8(library, session, space, offset, extended) + elif width == 16: + return in_16(library, session, space, offset, extended) + elif width == 32: + return in_32(library, session, space, offset, extended) + elif width == 64: + return in_64(library, session, space, offset, extended) + + raise ValueError('%s is not a valid size. Valid values are 8, 16, 32 or 64' % width) + + +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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from memory, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from memory, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from memory, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from memory, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + 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): + """Installs handlers for event callbacks. + + Corresponds to viInstallHandler function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param handler: Interpreted as a valid reference to a handler to be installed by a client application. + :param user_handle: A value specified by an application that can be used for identifying handlers + uniquely for an event type. Can be a regular python object (int, float, str, list + of floats or ints) or a ctypes object. + :returns: a handler descriptor which consists of three elements: + - handler (a python callable) + - user handle (a ctypes object) + - ctypes handler (ctypes object wrapping handler) + and return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + if user_handle is None: + converted_user_handle = None + else: + 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 = create_string_buffer(user_handle) + elif isinstance(user_handle, list): + for element in user_handle: + if not isinstance(element, int): + converted_user_handle = \ + (c_double * len(user_handle))(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)) + + set_user_handle_type(library, converted_user_handle) + converted_handler = ViHndlr(handler) + 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)) + + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param lock_type: Specifies the type of lock requested, either constants.AccessModes.exclusive_lock + or constants.AccessModes.shared_lock. + :param timeout: Absolute time period (in milliseconds) that a resource waits to get unlocked by the + locking session before returning an error. + :param requested_key: This parameter is not used and should be set to VI_NULL when lockType is VI_EXCLUSIVE_LOCK. + :return: access_key that can then be passed to other sessions to share the lock, return value of the library call. + :rtype: str, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param map_space: Specifies the address space to map. (Constants.*SPACE*) + :param map_base: Offset (in bytes) of the memory to be mapped. + :param map_size: Amount of memory to map (in bytes). + :param access: + :param suggested: If not Constants.NULL (0), the operating system attempts to map the memory to the address + specified in suggested. 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 + suggested. + + :return: address in your process space where the memory was mapped, return value of the library call. + :rtype: address, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param trigger_source: Source line from which to map. (Constants.TRIG*) + :param trigger_destination: Destination line to which to map. (Constants.TRIG*) + :param mode: + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viMapTrigger(session, trigger_source, trigger_destination, mode) + + +def memory_allocation(library, session, size, extended=False): + """Allocates memory from a resource's memory region. + + Corresponds to viMemAlloc* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param size: Specifies the size of the allocation. + :param extended: Use 64 bits offset independent of the platform. + :return: offset of the allocated memory, return value of the library call. + :rtype: offset, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param offset: Offset of the memory to free. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param source_space: Specifies the address space of the source. + :param source_offset: Offset of the starting address or register from which to read. + :param source_width: Specifies the data width of the source. + :param destination_space: Specifies the address space of the destination. + :param destination_offset: Offset of the starting address or register to which to write. + :param destination_width: Specifies the data width of the destination. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param source_space: Specifies the address space of the source. + :param source_offset: Offset of the starting address or register from which to read. + :param source_width: Specifies the data width of the source. + :param destination_space: Specifies the address space of the destination. + :param destination_offset: Offset of the starting address or register to which to write. + :param destination_width: Specifies the data width of the destination. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :return: Job identifier of this asynchronous move operation, return value of the library call. + :rtype: jobid, :class:`pyvisa.constants.StatusCode` + """ + 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(library, session, space, offset, length, width, extended=False): + """Moves a block of data to local memory from the specified address space and offset. + + Corresponds to viMoveIn* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param width: Number of bits to read per element. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from the bus, return value of the library call. + :rtype: list, :class:`pyvisa.constants.StatusCode` + """ + if width == 8: + return move_in_8(library, session, space, offset, length, extended) + elif width == 16: + return move_in_16(library, session, space, offset, length, extended) + elif width == 32: + return move_in_32(library, session, space, offset, length, extended) + elif width == 64: + return move_in_64(library, session, space, offset, length, extended) + + raise ValueError('%s is not a valid size. Valid values are 8, 16, 32 or 64' % width) + + +def move_in_8(library, session, space, offset, length, extended=False): + """Moves an 8-bit block of data from the specified address space and offset to local memory. + + Corresponds to viMoveIn8* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from the bus, return value of the library call. + :rtype: list, :class:`pyvisa.constants.StatusCode` + """ + 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 from the specified address space and offset to local memory. + + Corresponds to viMoveIn16* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from the bus, return value of the library call. + :rtype: list, :class:`pyvisa.constants.StatusCode` + """ + 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 from the specified address space and offset to local memory. + + Corresponds to viMoveIn32* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from the bus, return value of the library call. + :rtype: list, :class:`pyvisa.constants.StatusCode` + """ + 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 from the specified address space and offset to local memory. + + Corresponds to viMoveIn64* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from the bus, return value of the library call. + :rtype: list, :class:`pyvisa.constants.StatusCode` + """ + 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(library, session, space, offset, length, data, width, extended=False): + """Moves a block of data from local memory to the specified address space and offset. + + Corresponds to viMoveOut* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param data: Data to write to bus. + :param width: Number of bits to read per element. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + if width == 8: + return move_out_8(library, session, space, offset, length, data, extended) + elif width == 16: + return move_out_16(library, session, space, offset, length, data, extended) + elif width == 32: + return move_out_32(library, session, space, offset, length, data, extended) + elif width == 64: + return move_out_64(library, session, space, offset, length, data, extended) + + raise ValueError('%s is not a valid size. Valid values are 8, 16, 32 or 64' % width) + + +def move_out_8(library, session, space, offset, length, data, extended=False): + """Moves an 8-bit block of data from local memory to the specified address space and offset. + + Corresponds to viMoveOut8* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + + Corresponds to viMoveOut8 function of the VISA library. + """ + 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 to the specified address space and offset. + + Corresponds to viMoveOut16* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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 to the specified address space and offset. + + Corresponds to viMoveOut32* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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 to the specified address space and offset. + + Corresponds to viMoveOut64* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Resource Manager session (should always be a session returned from open_default_resource_manager()). + :param resource_name: Unique symbolic name of a resource. + :param access_mode: Specifies the mode by which the resource is to be accessed. (constants.AccessModes) + :param open_timeout: Specifies the maximum time period (in milliseconds) that this operation waits + before returning an error. + :return: Unique logical identifier reference to a session, return value of the library call. + :rtype: session, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :return: Unique logical identifier to a Default Resource Manager session, return value of the library call. + :rtype: session, :class:`pyvisa.constants.StatusCode` + """ + session = ViSession() + ret = library.viOpenDefaultRM(byref(session)) + return session.value, ret + + +def write_memory(library, session, space, offset, data, width, extended=False): + """Write in an 8-bit, 16-bit, 32-bit, value to the specified memory space and offset. + + Corresponds to viOut* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param data: Data to write to bus. + :param width: Number of bits to read. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + if width == 8: + return out_8(library, session, space, offset, data, extended) + elif width == 16: + return out_16(library, session, space, offset, data, extended) + elif width == 32: + return out_32(library, session, space, offset, data, extended) + + raise ValueError('%s is not a valid size. Valid values are 8, 16 or 32' % width) + + +def out_8(library, session, space, offset, data, extended=False): + """Write in an 8-bit value from the specified memory space and offset. + + Corresponds to viOut8* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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 in an 16-bit value from the specified memory space and offset. + + Corresponds to viOut16* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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 in an 32-bit value from the specified memory space and offset. + + Corresponds to viOut32* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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 in an 64-bit value from the specified memory space and offset. + + Corresponds to viOut64* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Resource Manager session (should always be the Default Resource Manager for VISA + returned from open_default_resource_manager()). + :param resource_name: Unique symbolic name of a resource. + :return: Resource information with interface type and board number, return value of the library call. + :rtype: :class:`pyvisa.highlevel.ResourceInfo`, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Resource Manager session (should always be the Default Resource Manager for VISA + returned from open_default_resource_manager()). + :param resource_name: Unique symbolic name of a resource. + :return: Resource information, return value of the library call. + :rtype: :class:`pyvisa.highlevel.ResourceInfo`, :class:`pyvisa.constants.StatusCode` + """ + 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(library, session, address, width): + """Read an 8, 16 or 32-bit value from the specified address. + + Corresponds to viPeek* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param width: Number of bits to read. + :return: Data read from bus, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + + if width == 8: + return peek_8(library, session, address) + elif width == 16: + return peek_16(library, session, address) + elif width == 32: + return peek_32(library, session, address) + elif width == 64: + return peek_64(library, session, address) + + raise ValueError('%s is not a valid size. Valid values are 8, 16, 32 or 64' % width) + + +def peek_8(library, session, address): + """Read an 8-bit value from the specified address. + + Corresponds to viPeek8 function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :return: Data read from bus, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :return: Data read from bus, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :return: Data read from bus, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :return: Data read from bus, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + value_64 = ViUInt64() + ret = library.viPeek64(session, address, byref(value_64)) + return value_64.value, ret + + +def poke(library, session, address, width, data): + """Writes an 8, 16 or 32-bit value from the specified address. + + Corresponds to viPoke* functions of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param width: Number of bits to read. + :param data: Data to be written to the bus. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + + if width == 8: + return poke_8(library, session, address, data) + elif width == 16: + return poke_16(library, session, address, data) + elif width == 32: + return poke_32(library, session, address, data) + + raise ValueError('%s is not a valid size. Valid values are 8, 16 or 32' % width) + + +def poke_8(library, session, address, data): + """Write an 8-bit value from the specified address. + + Corresponds to viPoke8 function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param data: value to be written to the bus. + :return: Data read from bus. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viPoke8(session, address, data) + + +def poke_16(library, session, address, data): + """Write an 16-bit value from the specified address. + + Corresponds to viPoke16 function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param data: value to be written to the bus. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viPoke16(session, address, data) + + +def poke_32(library, session, address, data): + """Write an 32-bit value from the specified address. + + Corresponds to viPoke32 function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param data: value to be written to the bus. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viPoke32(session, address, data) + + +def poke_64(library, session, address, data): + """Write an 64-bit value from the specified address. + + Corresponds to viPoke64 function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param data: value to be written to the bus. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param count: Number of bytes to be read. + :return: data read, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + 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_asynchronously(library, session, count): + """Reads data from device or interface asynchronously. + + Corresponds to viReadAsync function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param count: Number of bytes to be read. + :return: result, jobid, return value of the library call. + :rtype: ctypes buffer, jobid, :class:`pyvisa.constants.StatusCode` + """ + buffer = create_string_buffer(count) + job_id = ViJobId() + ret = library.viReadAsync(session, buffer, count, byref(job_id)) + return buffer, job_id, ret + + +def read_stb(library, session): + """Reads a status byte of the service request. + + Corresponds to viReadSTB function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :return: Service request status byte, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param filename: Name of file to which data will be written. + :param count: Number of bytes to be read. + :return: Number of bytes actually transferred, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + return_count = ViUInt32() + ret = library.viReadToFile(session, filename, count, return_count) + return return_count, ret + + +def set_attribute(library, session, attribute, attribute_state): + """Sets the state of an attribute. + + Corresponds to viSetAttribute function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param attribute: Attribute for which the state is to be modified. (Attributes.*) + :param attribute_state: The state of the attribute to be set for the specified object. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viSetAttribute(session, attribute, attribute_state) + + +def set_buffer(library, session, mask, size): + """Sets the size for the formatted I/O and/or low-level I/O communication buffer(s). + + Corresponds to viSetBuf function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param mask: Specifies the type of buffer. (Constants.READ_BUF, .WRITE_BUF, .IO_IN_BUF, .IO_OUT_BUF) + :param size: The size to be set for the specified buffer(s). + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viSetBuf(session, mask, size) + + +def status_description(library, session, status): + """Returns a user-readable description of the status code passed to the operation. + + Corresponds to viStatusDesc function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param status: Status code to interpret. + :return: - The user-readable string interpretation of the status code passed to the operation, + - return value of the library call. + :rtype: - unicode (Py2) or str (Py3) + - :class:`pyvisa.constants.StatusCode` + """ + description = create_string_buffer(256) + ret = library.viStatusDesc(session, status, description) + return buffer_to_text(description), ret + + +def terminate(library, session, degree, job_id): + """Requests a VISA session to terminate normal execution of an operation. + + Corresponds to viTerminate function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param degree: Constants.NULL + :param job_id: Specifies an operation identifier. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viTerminate(session, degree, job_id) + + +def uninstall_handler(library, session, event_type, handler, user_handle=None): + """Uninstalls handlers for events. + + Corresponds to viUninstallHandler function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param handler: Interpreted as a valid reference to a handler to be uninstalled by a client application. + :param user_handle: The user_handle (a ctypes object) in the returned value from install_handler. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + set_user_handle_type(library, user_handle) + if user_handle != None: + user_handle = byref(user_handle) + return library.viUninstallHandler(session, event_type, handler, user_handle) + + +def unlock(library, session): + """Relinquishes a lock for the specified resource. + + Corresponds to viUnlock function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viUnlock(session) + + +def unmap_address(library, session): + """Unmaps memory space previously mapped by map_address(). + + Corresponds to viUnmapAddress function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return library.viUnmapAddress(session) + + +def unmap_trigger(library, session, trigger_source, trigger_destination): + """Undo a previous map from the specified trigger source line to the specified destination line. + + Corresponds to viUnmapTrigger function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param trigger_source: Source line used in previous map. (Constants.TRIG*) + :param trigger_destination: Destination line used in previous map. (Constants.TRIG*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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): + """Performs a USB control pipe transfer from the device. + + Corresponds to viUsbControlIn function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param request_type_bitmap_field: bmRequestType parameter of the setup stage of a USB control transfer. + :param request_id: bRequest parameter of the setup stage of a USB control transfer. + :param request_value: wValue parameter of the setup stage of a USB control transfer. + :param index: wIndex parameter of the setup stage of a USB control transfer. + This is usually the index of the interface or endpoint. + :param length: 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. + :return: - The data buffer that receives the data from the optional data stage of the control transfer + - return value of the library call. + :rtype: - bytes + - :class:`pyvisa.constants.StatusCode` + """ + 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=""): + """Performs a USB control pipe transfer to the device. + + Corresponds to viUsbControlOut function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param request_type_bitmap_field: bmRequestType parameter of the setup stage of a USB control transfer. + :param request_id: bRequest parameter of the setup stage of a USB control transfer. + :param request_value: wValue parameter of the setup stage of a USB control transfer. + :param index: wIndex parameter of the setup stage of a USB control transfer. + This is usually the index of the interface or endpoint. + :param data: The data buffer that sends the data in the optional data stage of the control transfer. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + 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): + """Sends the device a miscellaneous command or query and/or retrieves the response to a previous query. + + Corresponds to viVxiCommandQuery function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param mode: Specifies whether to issue a command and/or retrieve a response. (Constants.VXI_CMD*, .VXI_RESP*) + :param command: The miscellaneous command to send. + :return: The response retrieved from the device, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + response = ViUInt32() + ret = library.viVxiCommandQuery(session, mode, command, byref(response)) + return response.value, ret + + +def wait_on_event(library, session, in_event_type, timeout): + """Waits for an occurrence of the specified event for a given session. + + Corresponds to viWaitOnEvent function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param in_event_type: Logical identifier of the event(s) to wait for. + :param timeout: 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. + :return: - Logical identifier of the event actually received + - A handle specifying the unique occurrence of an event + - return value of the library call. + :rtype: - eventtype + - event + - :class:`pyvisa.constants.StatusCode` + """ + 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): + """Writes data to device or interface synchronously. + + Corresponds to viWrite function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param data: data to be written. + :type data: str + :return: Number of bytes actually transferred, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + 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): + """Writes data to device or interface asynchronously. + + Corresponds to viWriteAsync function of the VISA library. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param data: data to be written. + :return: Job ID of this asynchronous write operation, return value of the library call. + :rtype: jobid, :class:`pyvisa.constants.StatusCode` + """ + 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. + + :param library: the visa library wrapped by ctypes. + :param session: Unique logical identifier to a session. + :param filename: Name of file from which data will be read. + :param count: Number of bytes to be written. + :return: Number of bytes actually transferred, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + return_count = ViUInt32() + ret = library.viWriteFromFile(session, filename, count, return_count) + return return_count, ret diff --git a/pyvisa/ctwrapper/highlevel.py b/pyvisa/ctwrapper/highlevel.py new file mode 100644 index 0000000..8d51a71 --- /dev/null +++ b/pyvisa/ctwrapper/highlevel.py @@ -0,0 +1,256 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.ctwrapper.highlevel + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Highlevel wrapper of the VISA Library. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import logging +import warnings + +from pyvisa import constants, errors, highlevel, logger +from pyvisa.compat import integer_types, OrderedDict + +from .cthelper import Library, find_library +from . import functions + + +logger = logging.LoggerAdapter(logger, {'backend': 'ni'}) + + +def add_visa_methods(aclass): + for method in functions.visa_functions: + setattr(aclass, method, getattr(functions, method)) + return aclass + + +def _args_to_str(args): + out = [] + for arg in args: + try: + # noinspection PyProtectedMember + out.append(str(arg._obj)) + except AttributeError: + out.append(arg) + return tuple(out) + + +@add_visa_methods +class NIVisaLibrary(highlevel.VisaLibraryBase): + """High level NI-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 = NIVisaLibrary() + + But you can also specify the path: + + >>> visa_library = NIVisaLibrary('/my/path/visa.so') + + :param library_path: path of the VISA library. + """ + + @staticmethod + def get_library_paths(): + """Return a tuple of possible library paths. + + :rtype: tuple + """ + + from ..util import LibraryPath, read_user_library_path + + user_lib = read_user_library_path() + tmp = [find_library(library_path) + for library_path in ('visa', 'visa32', 'visa32.dll', 'visa64', 'visa64.dll')] + + tmp = [LibraryPath(library_path) + for library_path in set(tmp) + if library_path is not None] + + logger.debug('Automatically found library files: %s' % tmp) + + if user_lib: + user_lib = LibraryPath(user_lib, 'user') + try: + tmp.remove(user_lib) + except ValueError: + pass + tmp.insert(0, user_lib) + + return tuple(tmp) + + @staticmethod + def get_debug_info(): + """Return a list of lines with backend info. + """ + from pyvisa import __version__ + d = OrderedDict() + d['Version'] = '%s (bundled with PyVISA)' % __version__ + + paths = NIVisaLibrary.get_library_paths() + + for ndx, visalib in enumerate(paths, 1): + nfo = OrderedDict() + nfo['found by'] = visalib.found_by + nfo['bitness'] = visalib.bitness + try: + lib = NIVisaLibrary(visalib) + sess, _ = lib.open_default_resource_manager() + nfo['Vendor'] = str(lib.get_attribute(sess, constants.VI_ATTR_RSRC_MANF_NAME)[0]) + nfo['Impl. Version'] = str(lib.get_attribute(sess, constants.VI_ATTR_RSRC_IMPL_VERSION)[0]) + nfo['Spec. Version'] = str(lib.get_attribute(sess, constants.VI_ATTR_RSRC_SPEC_VERSION)[0]) + lib.close(sess) + except Exception as e: + e = str(e) + if 'No matching architecture' in e: + nfo['Could not get more info'] = 'Interpreter and library have different bitness.' + else: + nfo['Could not get more info'] = str(e).split('\n') + + d['#%d: %s' % (ndx, visalib)] = nfo + + if not paths: + d['Binary library'] = 'Not found' + + return d + + def _init(self): + try: + lib = Library(self.library_path) + except OSError as exc: + raise errors.LibraryError.from_exception(exc, self.library_path) + + self.lib = lib + + # 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, func, arguments): + """Check return values for errors and warnings. + """ + + logger.debug('%s%s -> %r', + func.__name__, _args_to_str(arguments), ret_value, + extra=self._logging_extra) + + try: + ret_value = constants.StatusCode(ret_value) + except ValueError: + pass + + self._last_status = ret_value + + # 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', ): + # noinspection PyProtectedMember + session = session._obj.value + + if isinstance(session, integer_types): + self._last_status_in_session[session] = ret_value + else: + # Functions that might or might 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))) + + if ret_value < 0: + raise errors.VisaIOError(ret_value) + + if ret_value in self.issue_warning_on: + if session and ret_value not in self._ignore_warning_in_session[session]: + warnings.warn(errors.VisaIOWarning(ret_value), stacklevel=2) + + return ret_value + + def list_resources(self, session, query='?*::INSTR'): + """Returns a tuple of all connected devices matching query. + + note: 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'. + + :param query: a VISA Resource Regular Expression used to match devices. + """ + + resources = [] + + try: + find_list, return_counter, instrument_description, err = self.find_resources(session, query) + except errors.VisaIOError as e: + if e.error_code == constants.StatusCode.error_resource_not_found: + return tuple() + raise e + + resources.append(instrument_description) + for i in range(return_counter - 1): + resources.append(self.find_next(find_list)[0]) + + self.close(find_list) + + return tuple(resource for resource in resources) + diff --git a/pyvisa/ctwrapper/types.py b/pyvisa/ctwrapper/types.py new file mode 100644 index 0000000..96cde28 --- /dev/null +++ b/pyvisa/ctwrapper/types.py @@ -0,0 +1,157 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.ctwrapper.types + ~~~~~~~~~~~~~~~~~~~~~~ + + 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 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import ctypes as _ctypes + +from .cthelper import PYTHON3, 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) + + +if PYTHON3: + 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 + +else: + + class ViString(object): + + @classmethod + def from_param(cls, obj): + if isinstance(obj, str): + return obj + elif isinstance(obj, unicode): + return obj.encode('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): + 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): + + @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) diff --git a/pyvisa/errors.py b/pyvisa/errors.py new file mode 100644 index 0000000..9c758fd --- /dev/null +++ b/pyvisa/errors.py @@ -0,0 +1,535 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.errors + ~~~~~~~~~~~~~ + + Defines exceptions hierarchy and textual explanations of VISA completion and error codes. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, print_function, absolute_import + +from . import util, constants +from .constants import * + +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([VI_SUCCESS_MAX_CNT, VI_SUCCESS_DEV_NPRESENT, + VI_SUCCESS_SYNC, VI_WARN_QUEUE_OVERFLOW, + VI_WARN_CONFIG_NLOADED, VI_WARN_NULL_OBJECT, + VI_WARN_NSUP_ATTR_STATE, VI_WARN_UNKNOWN_STATUS, + VI_WARN_NSUP_BUF, VI_WARN_EXT_FUNC_NIMPL]) + + +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): + 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): + 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): + 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): + 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, handler, user_handle): + 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): + return (UnknownHandler, (self.event_type, self.handler, self.user_handle)) + + +class OSNotSupported(Error): + + def __init__(self, os): + super(OSNotSupported, self).__init__(os + " is not yet supported by PyVISA") + self.os = os + + def __reduce__(self): + return (OSNotSupported, (self.os,)) + + +class InvalidBinaryFormat(Error): + + def __init__(self, description=""): + if description: + description = ": " + description + super(InvalidBinaryFormat, self).__init__("Unrecognized binary data format" + description) + self.description = description + + def __reduce__(self): + return (InvalidBinaryFormat, (self.description,)) + + +class InvalidSession(Error): + """Exception raised when an invalid session is requested. + """ + + def __init__(self): + super(InvalidSession, self).__init__('Invalid session handle. The resource might be closed.') + + def __reduce__(self): + return (InvalidSession, ()) + + +class LibraryError(OSError, Error): + + @classmethod + def from_exception(cls, exc, filename): + + 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): + 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)) + + +def _args_to_str(args, kwargs): + return 'args=%s, kwargs=%s' % (args, kwargs) + + +def return_handler(module_logger, first_is_session=True): + """Decorator for VISA library classes. + """ + + 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 = constants.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 diff --git a/pyvisa/highlevel.py b/pyvisa/highlevel.py new file mode 100644 index 0000000..8b777c3 --- /dev/null +++ b/pyvisa/highlevel.py @@ -0,0 +1,1732 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.highlevel + ~~~~~~~~~~~~~~~~ + + High level Visa library wrapper. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import contextlib +import collections +import pkgutil +import os +from collections import defaultdict + +from . import logger +from . import constants +from . import errors +from . import rname + +#: 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. +#: :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 = collections.namedtuple('ResourceInfo', + 'interface_type interface_board_number ' + 'resource_class resource_name alias') + + +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. + + The default VisaLibrary class is :class:`pyvisa.ctwrapper.highlevel.NIVisaLibrary`, + which implements a ctypes wrapper around the NI-VISA library. + + 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 visa + >>> rm = visa.ResourceManager("/path/to/my/libvisa.so.7") + >>> lib = rm.visalib + """ + + #: Default ResourceManager instance for this library. + resource_manager = None + + #: Maps library path to VisaLibrary object + _registry = dict() + + #: Last return value of the library. + _last_status = 0 + + #: Maps session handle to last status. dict() + _last_status_in_session = None + + #: Maps session handle to warnings to ignore. defaultdict(set) + _ignore_warning_in_session = None + + #: Contains all installed event handlers. + #: Its elements are tuples with three elements: The handler itself (a Python + #: callable), the user handle (as a ct object) and the handler again, this + #: time as a ct object created with CFUNCTYPE. + handlers = None + + #: Set error codes on which to issue a warning. set + issue_warning_on = None + + def __new__(cls, library_path=''): + 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 (cls, library_path) in cls._registry: + return cls._registry[(cls, library_path)] + + obj = super(VisaLibraryBase, cls).__new__(cls) + + obj.library_path = library_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) + + logger.debug('Created library wrapper for %s', library_path) + + cls._registry[(cls, library_path)] = obj + + return obj + + @staticmethod + def get_library_paths(): + """Override this method to return an iterable of possible library_paths + to try in case that no argument is given. + """ + return 'unset', + + @staticmethod + def get_debug_info(): + """Override this method to return an iterable of lines with the backend debug details. + """ + return ['Does not provide debug info'] + + def _init(self): + """Override this method to customize VisaLibrary initialization. + """ + pass + + def __str__(self): + return 'Visa Library at %s' % self.library_path + + def __repr__(self): + return '' % self.library_path + + @property + def last_status(self): + """Last return value of the library. + """ + return self._last_status + + def get_last_status_in_session(self, session): + """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, *warnings_constants): + """A session dependent context for ignoring warnings + + :param session: Unique logical identifier to a session. + :param warnings_constants: 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, event_type, handler, user_handle=None): + """Installs handlers for event callbacks. + + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param handler: Interpreted as a valid reference to a handler to be installed by a client application. + :param user_handle: A value specified by an application that can be used for identifying handlers + uniquely for an event type. + :returns: user handle (a ctypes object) + """ + try: + new_handler = self.install_handler(session, event_type, handler, user_handle) + except TypeError as e: + raise errors.VisaTypeError(str(e)) + + self.handlers[session].append(new_handler + (event_type,)) + return new_handler[1] + + def uninstall_visa_handler(self, session, event_type, handler, user_handle=None): + """Uninstalls handlers for events. + + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param handler: Interpreted as a valid reference to a handler to be uninstalled by a client application. + :param user_handle: The user handle (ctypes object or None) returned by install_visa_handler. + """ + for ndx, element in enumerate(self.handlers[session]): + if element[0] is handler and element[1] is user_handle and element[4] == 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): + for element in self.handlers[session]: + self.uninstall_handler(session, element[4], element[2], element[1]) + del self.handlers[session] + + def uninstall_all_visa_handlers(self, session): + """Uninstalls all previously installed handlers for a particular session. + + :param session: 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, space, offset, width, extended=False): + """Reads in an 8-bit, 16-bit, 32-bit, or 64-bit value from the specified memory space and offset. + + Corresponds to viIn* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param width: Number of bits to read. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from memory, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + if width == 8: + return self.in_8(session, space, offset, extended) + elif width == 16: + return self.in_16(session, space, offset, extended) + elif width == 32: + return self.in_32(session, space, offset, extended) + elif width == 64: + return self.in_64(session, space, offset, extended) + + raise ValueError('%s is not a valid size. Valid values are 8, 16, 32 or 64' % width) + + def write_memory(self, session, space, offset, data, width, extended=False): + """Write in an 8-bit, 16-bit, 32-bit, 64-bit value to the specified memory space and offset. + + Corresponds to viOut* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param data: Data to write to bus. + :param width: Number of bits to read. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + if width == 8: + return self.out_8(session, space, offset, data, extended) + elif width == 16: + return self.out_16(session, space, offset, data, extended) + elif width == 32: + return self.out_32(session, space, offset, data, extended) + elif width == 64: + return self.out_64(session, space, offset, data, extended) + + raise ValueError('%s is not a valid size. Valid values are 8, 16, 32, or 64' % width) + + def move_in(self, session, space, offset, length, width, extended=False): + """Moves a block of data to local memory from the specified address space and offset. + + Corresponds to viMoveIn* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param width: Number of bits to read per element. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from the bus, return value of the library call. + :rtype: list, :class:`pyvisa.constants.StatusCode` + """ + if width == 8: + return self.move_in_8(session, space, offset, length, extended) + elif width == 16: + return self.move_in_16(session, space, offset, length, extended) + elif width == 32: + return self.move_in_32(session, space, offset, length, extended) + elif width == 64: + return self.move_in_64(session, space, offset, length, extended) + + raise ValueError('%s is not a valid size. Valid values are 8, 16, 32 or 64' % width) + + def move_out(self, session, space, offset, length, data, width, extended=False): + """Moves a block of data from local memory to the specified address space and offset. + + Corresponds to viMoveOut* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param data: Data to write to bus. + :param width: Number of bits to read per element. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + if width == 8: + return self.move_out_8(session, space, offset, length, data, extended) + elif width == 16: + return self.move_out_16(session, space, offset, length, data, extended) + elif width == 32: + return self.move_out_32(session, space, offset, length, data, extended) + elif width == 64: + return self.move_out_64(session, space, offset, length, data, extended) + + raise ValueError('%s is not a valid size. Valid values are 8, 16, 32 or 64' % width) + + def peek(self, session, address, width): + """Read an 8, 16, 32, or 64-bit value from the specified address. + + Corresponds to viPeek* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param width: Number of bits to read. + :return: Data read from bus, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + + if width == 8: + return self.peek_8(session, address) + elif width == 16: + return self.peek_16(session, address) + elif width == 32: + return self.peek_32(session, address) + elif width == 64: + return self.peek_64(session, address) + + raise ValueError('%s is not a valid size. Valid values are 8, 16, 32 or 64' % width) + + def poke(self, session, address, width, data): + """Writes an 8, 16, 32, or 64-bit value from the specified address. + + Corresponds to viPoke* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param width: Number of bits to read. + :param data: Data to be written to the bus. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + + if width == 8: + return self.poke_8(session, address, data) + elif width == 16: + return self.poke_16(session, address, data) + elif width == 32: + return self.poke_32(session, address, data) + elif width == 64: + return self.poke_64(session, address, data) + + raise ValueError('%s is not a valid size. Valid values are 8, 16, 32, or 64' % width) + + # Methods that VISA Library implementations must implement + + def assert_interrupt_signal(self, session, mode, status_id): + """Asserts the specified interrupt or signal. + + Corresponds to viAssertIntrSignal function of the VISA library. + + :param session: Unique logical identifier to a session. + :param mode: How to assert the interrupt. (Constants.ASSERT*) + :param status_id: This is the status value to be presented during an interrupt acknowledge cycle. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def assert_trigger(self, session, protocol): + """Asserts software or hardware trigger. + + Corresponds to viAssertTrigger function of the VISA library. + + :param session: Unique logical identifier to a session. + :param protocol: Trigger protocol to use during assertion. (Constants.PROT*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def assert_utility_signal(self, session, line): + """Asserts or deasserts the specified utility bus signal. + + Corresponds to viAssertUtilSignal function of the VISA library. + + :param session: Unique logical identifier to a session. + :param line: specifies the utility bus signal to assert. (Constants.VI_UTIL_ASSERT*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def buffer_read(self, session, count): + """Reads data from device or interface through the use of a formatted I/O read buffer. + + Corresponds to viBufRead function of the VISA library. + + :param session: Unique logical identifier to a session. + :param count: Number of bytes to be read. + :return: data read, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def buffer_write(self, session, data): + """Writes data to a formatted I/O write buffer synchronously. + + Corresponds to viBufWrite function of the VISA library. + + :param session: Unique logical identifier to a session. + :param data: data to be written. + :type data: bytes + :return: number of written bytes, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def clear(self, session): + """Clears a device. + + Corresponds to viClear function of the VISA library. + + :param session: Unique logical identifier to a session. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def close(self, session): + """Closes the specified session, event, or find list. + + Corresponds to viClose function of the VISA library. + + :param session: Unique logical identifier to a session, event, or find list. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def disable_event(self, session, event_type, mechanism): + """Disables notification of the specified event type(s) via the specified mechanism(s). + + Corresponds to viDisableEvent function of the VISA library. + + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param mechanism: Specifies event handling mechanisms to be disabled. + (Constants.VI_QUEUE, .VI_HNDLR, .VI_SUSPEND_HNDLR, .VI_ALL_MECH) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def discard_events(self, session, event_type, mechanism): + """Discards event occurrences for specified event types and mechanisms in a session. + + Corresponds to viDiscardEvents function of the VISA library. + + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param mechanism: Specifies event handling mechanisms to be discarded. + (Constants.VI_QUEUE, .VI_HNDLR, .VI_SUSPEND_HNDLR, .VI_ALL_MECH) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def enable_event(self, 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. + + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param mechanism: Specifies event handling mechanisms to be enabled. + (Constants.VI_QUEUE, .VI_HNDLR, .VI_SUSPEND_HNDLR) + :param context: + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def flush(self, session, mask): + """Manually flushes the specified buffers associated with formatted I/O operations and/or serial communication. + + Corresponds to viFlush function of the VISA library. + + :param session: Unique logical identifier to a session. + :param mask: Specifies the action to be taken with flushing the buffer. + (Constants.READ*, .WRITE*, .IO*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def get_attribute(self, session, attribute): + """Retrieves the state of an attribute. + + Corresponds to viGetAttribute function of the VISA library. + + :param session: Unique logical identifier to a session, event, or find list. + :param attribute: Resource attribute for which the state query is made (see Attributes.*) + :return: The state of the queried attribute for a specified resource, return value of the library call. + :rtype: unicode (Py2) or str (Py3), list or other type, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def gpib_command(self, session, data): + """Write GPIB command bytes on the bus. + + Corresponds to viGpibCommand function of the VISA library. + + :param session: Unique logical identifier to a session. + :param data: data tor write. + :type data: bytes + :return: Number of written bytes, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def gpib_control_atn(self, session, mode): + """Specifies the state of the ATN line and the local active controller state. + + Corresponds to viGpibControlATN function of the VISA library. + + :param session: Unique logical identifier to a session. + :param mode: Specifies the state of the ATN line and optionally the local active controller state. + (Constants.VI_GPIB_ATN*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def gpib_control_ren(self, session, mode): + """Controls the state of the GPIB Remote Enable (REN) interface line, and optionally the remote/local + state of the device. + + Corresponds to viGpibControlREN function of the VISA library. + + :param session: Unique logical identifier to a session. + :param mode: Specifies the state of the REN line and optionally the device remote/local state. + (Constants.VI_GPIB_REN*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def gpib_pass_control(self, session, primary_address, secondary_address): + """Tell the GPIB device at the specified address to become controller in charge (CIC). + + Corresponds to viGpibPassControl function of the VISA library. + + :param session: Unique logical identifier to a session. + :param primary_address: Primary address of the GPIB device to which you want to pass control. + :param secondary_address: 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. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def gpib_send_ifc(self, session): + """Pulse the interface clear line (IFC) for at least 100 microseconds. + + Corresponds to viGpibSendIFC function of the VISA library. + + :param session: Unique logical identifier to a session. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def in_8(self, 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. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from memory, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def in_16(self, 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. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from memory, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def in_32(self, 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. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from memory, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def in_64(self, 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. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from memory, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def install_handler(self, session, event_type, handler, user_handle): + """Installs handlers for event callbacks. + + Corresponds to viInstallHandler function of the VISA library. + + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param handler: Interpreted as a valid reference to a handler to be installed by a client application. + :param user_handle: A value specified by an application that can be used for identifying handlers + uniquely for an event type. + :returns: a handler descriptor which consists of three elements: + - handler (a python callable) + - user handle (a ctypes object) + - ctypes handler (ctypes object wrapping handler) + and return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def list_resources(self, session, query='?*::INSTR'): + """Returns a tuple of all connected devices matching query. + + :param query: regular expression used to match devices. + """ + raise NotImplementedError + + def lock(self, session, lock_type, timeout, requested_key=None): + """Establishes an access mode to the specified resources. + + Corresponds to viLock function of the VISA library. + + :param session: Unique logical identifier to a session. + :param lock_type: Specifies the type of lock requested, either Constants.EXCLUSIVE_LOCK or Constants.SHARED_LOCK. + :param timeout: Absolute time period (in milliseconds) that a resource waits to get unlocked by the + locking session before returning an error. + :param requested_key: This parameter is not used and should be set to VI_NULL when lockType is VI_EXCLUSIVE_LOCK. + :return: access_key that can then be passed to other sessions to share the lock, return value of the library call. + :rtype: str, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def map_address(self, 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. + + :param session: Unique logical identifier to a session. + :param map_space: Specifies the address space to map. (Constants.*SPACE*) + :param map_base: Offset (in bytes) of the memory to be mapped. + :param map_size: Amount of memory to map (in bytes). + :param access: + :param suggested: If not Constants.VI_NULL (0), the operating system attempts to map the memory to the address + specified in suggested. 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 + suggested. + + :return: address in your process space where the memory was mapped, return value of the library call. + :rtype: address, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def map_trigger(self, 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. + + :param session: Unique logical identifier to a session. + :param trigger_source: Source line from which to map. (Constants.VI_TRIG*) + :param trigger_destination: Destination line to which to map. (Constants.VI_TRIG*) + :param mode: + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def memory_allocation(self, session, size, extended=False): + """Allocates memory from a resource's memory region. + + Corresponds to viMemAlloc* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param size: Specifies the size of the allocation. + :param extended: Use 64 bits offset independent of the platform. + :return: offset of the allocated memory, return value of the library call. + :rtype: offset, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def memory_free(self, session, offset, extended=False): + """Frees memory previously allocated using the memory_allocation() operation. + + Corresponds to viMemFree* function of the VISA library. + + :param session: Unique logical identifier to a session. + :param offset: Offset of the memory to free. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def move(self, 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. + + :param session: Unique logical identifier to a session. + :param source_space: Specifies the address space of the source. + :param source_offset: Offset of the starting address or register from which to read. + :param source_width: Specifies the data width of the source. + :param destination_space: Specifies the address space of the destination. + :param destination_offset: Offset of the starting address or register to which to write. + :param destination_width: Specifies the data width of the destination. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def move_asynchronously(self, 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. + + :param session: Unique logical identifier to a session. + :param source_space: Specifies the address space of the source. + :param source_offset: Offset of the starting address or register from which to read. + :param source_width: Specifies the data width of the source. + :param destination_space: Specifies the address space of the destination. + :param destination_offset: Offset of the starting address or register to which to write. + :param destination_width: Specifies the data width of the destination. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :return: Job identifier of this asynchronous move operation, return value of the library call. + :rtype: jobid, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def move_in_8(self, session, space, offset, length, extended=False): + """Moves an 8-bit block of data from the specified address space and offset to local memory. + + Corresponds to viMoveIn8* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from the bus, return value of the library call. + :rtype: list, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def move_in_16(self, session, space, offset, length, extended=False): + """Moves an 16-bit block of data from the specified address space and offset to local memory. + + Corresponds to viMoveIn16* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from the bus, return value of the library call. + :rtype: list, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def move_in_32(self, session, space, offset, length, extended=False): + """Moves an 32-bit block of data from the specified address space and offset to local memory. + + Corresponds to viMoveIn32* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from the bus, return value of the library call. + :rtype: list, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def move_in_64(self, session, space, offset, length, extended=False): + """Moves an 64-bit block of data from the specified address space and offset to local memory. + + Corresponds to viMoveIn64* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from the bus, return value of the library call. + :rtype: list, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def move_out_8(self, session, space, offset, length, data, extended=False): + """Moves an 8-bit block of data from local memory to the specified address space and offset. + + Corresponds to viMoveOut8* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + + Corresponds to viMoveOut8 function of the VISA library. + """ + raise NotImplementedError + + def move_out_16(self, session, space, offset, length, data, extended=False): + """Moves an 16-bit block of data from local memory to the specified address space and offset. + + Corresponds to viMoveOut16* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def move_out_32(self, session, space, offset, length, data, extended=False): + """Moves an 32-bit block of data from local memory to the specified address space and offset. + + Corresponds to viMoveOut32* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def move_out_64(self, session, space, offset, length, data, extended=False): + """Moves an 64-bit block of data from local memory to the specified address space and offset. + + Corresponds to viMoveOut64* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def open(self, 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. + + :param session: Resource Manager session (should always be a session returned from open_default_resource_manager()). + :param resource_name: Unique symbolic name of a resource. + :param access_mode: Specifies the mode by which the resource is to be accessed. + :type access_mode: :class:`pyvisa.constants.AccessModes` + :param open_timeout: Specifies the maximum time period (in milliseconds) that this operation waits + before returning an error. + :return: Unique logical identifier reference to a session, return value of the library call. + :rtype: session, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def open_default_resource_manager(self): + """This function returns a session to the Default Resource Manager resource. + + Corresponds to viOpenDefaultRM function of the VISA library. + + :return: Unique logical identifier to a Default Resource Manager session, return value of the library call. + :rtype: session, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def out_8(self, session, space, offset, data, extended=False): + """Write in an 8-bit value from the specified memory space and offset. + + Corresponds to viOut8* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def out_16(self, session, space, offset, data, extended=False): + """Write in an 16-bit value from the specified memory space and offset. + + Corresponds to viOut16* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def out_32(self, session, space, offset, data, extended=False): + """Write in an 32-bit value from the specified memory space and offset. + + Corresponds to viOut32* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def out_64(self, session, space, offset, data, extended=False): + """Write in an 64-bit value from the specified memory space and offset. + + Corresponds to viOut64* functions of the VISA library. + + :param session: Unique logical identifier to a session. + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param data: Data to write to bus. + :param extended: Use 64 bits offset independent of the platform. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def parse_resource(self, session, resource_name): + """Parse a resource string to get the interface information. + + Corresponds to viParseRsrc function of the VISA library. + + :param session: Resource Manager session (should always be the Default Resource Manager for VISA + returned from open_default_resource_manager()). + :param resource_name: Unique symbolic name of a resource. + :return: Resource information with interface type and board number, return value of the library call. + :rtype: :class:`pyvisa.highlevel.ResourceInfo`, :class:`pyvisa.constants.StatusCode` + """ + return self.parse_resource_extended(session, resource_name) + + def parse_resource_extended(self, session, resource_name): + """Parse a resource string to get extended interface information. + + Corresponds to viParseRsrcEx function of the VISA library. + + :param session: Resource Manager session (should always be the Default Resource Manager for VISA + returned from open_default_resource_manager()). + :param resource_name: Unique symbolic name of a resource. + :return: Resource information, return value of the library call. + :rtype: :class:`pyvisa.highlevel.ResourceInfo`, :class:`pyvisa.constants.StatusCode` + """ + try: + parsed = rname.parse_resource_name(resource_name) + + return (ResourceInfo(parsed.interface_type_const, + parsed.board, + parsed.resource_class, + str(parsed), None), + constants.StatusCode.success) + except ValueError: + return 0, constants.StatusCode.error_invalid_resource_name + + def peek_8(self, session, address): + """Read an 8-bit value from the specified address. + + Corresponds to viPeek8 function of the VISA library. + + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :return: Data read from bus, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def peek_16(self, session, address): + """Read an 16-bit value from the specified address. + + Corresponds to viPeek16 function of the VISA library. + + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :return: Data read from bus, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def peek_32(self, session, address): + """Read an 32-bit value from the specified address. + + Corresponds to viPeek32 function of the VISA library. + + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :return: Data read from bus, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def peek_64(self, session, address): + """Read an 64-bit value from the specified address. + + Corresponds to viPeek64 function of the VISA library. + + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :return: Data read from bus, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def poke_8(self, session, address, data): + """Write an 8-bit value from the specified address. + + Corresponds to viPoke8 function of the VISA library. + + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param data: value to be written to the bus. + :return: Data read from bus. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def poke_16(self, session, address, data): + """Write an 16-bit value from the specified address. + + Corresponds to viPoke16 function of the VISA library. + + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param data: value to be written to the bus. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def poke_32(self, session, address, data): + """Write an 32-bit value from the specified address. + + Corresponds to viPoke32 function of the VISA library. + + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param data: value to be written to the bus. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def poke_64(self, session, address, data): + """Write an 64-bit value from the specified address. + + Corresponds to viPoke64 function of the VISA library. + + :param session: Unique logical identifier to a session. + :param address: Source address to read the value. + :param data: value to be written to the bus. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def read(self, session, count): + """Reads data from device or interface synchronously. + + Corresponds to viRead function of the VISA library. + + :param session: Unique logical identifier to a session. + :param count: Number of bytes to be read. + :return: data read, return value of the library call. + :rtype: bytes, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def read_asynchronously(self, session, count): + """Reads data from device or interface asynchronously. + + Corresponds to viReadAsync function of the VISA library. + + :param session: Unique logical identifier to a session. + :param count: Number of bytes to be read. + :return: result, jobid, return value of the library call. + :rtype: ctypes buffer, jobid, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def read_stb(self, session): + """Reads a status byte of the service request. + + Corresponds to viReadSTB function of the VISA library. + + :param session: Unique logical identifier to a session. + :return: Service request status byte, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def read_to_file(self, session, filename, count): + """Read data synchronously, and store the transferred data in a file. + + Corresponds to viReadToFile function of the VISA library. + + :param session: Unique logical identifier to a session. + :param filename: Name of file to which data will be written. + :param count: Number of bytes to be read. + :return: Number of bytes actually transferred, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def set_attribute(self, session, attribute, attribute_state): + """Sets the state of an attribute. + + Corresponds to viSetAttribute function of the VISA library. + + :param session: Unique logical identifier to a session. + :param attribute: Attribute for which the state is to be modified. (Attributes.*) + :param attribute_state: The state of the attribute to be set for the specified object. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def set_buffer(self, session, mask, size): + """Sets the size for the formatted I/O and/or low-level I/O communication buffer(s). + + Corresponds to viSetBuf function of the VISA library. + + :param session: Unique logical identifier to a session. + :param mask: Specifies the type of buffer. (Constants.VI_READ_BUF, .VI_WRITE_BUF, .VI_IO_IN_BUF, .VI_IO_OUT_BUF) + :param size: The size to be set for the specified buffer(s). + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def status_description(self, session, status): + """Returns a user-readable description of the status code passed to the operation. + + Corresponds to viStatusDesc function of the VISA library. + + :param session: Unique logical identifier to a session. + :param status: Status code to interpret. + :return: - The user-readable string interpretation of the status code passed to the operation, + - return value of the library call. + :rtype: - unicode (Py2) or str (Py3) + - :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def terminate(self, session, degree, job_id): + """Requests a VISA session to terminate normal execution of an operation. + + Corresponds to viTerminate function of the VISA library. + + :param session: Unique logical identifier to a session. + :param degree: Constants.NULL + :param job_id: Specifies an operation identifier. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def uninstall_handler(self, session, event_type, handler, user_handle=None): + """Uninstalls handlers for events. + + Corresponds to viUninstallHandler function of the VISA library. + + :param session: Unique logical identifier to a session. + :param event_type: Logical event identifier. + :param handler: Interpreted as a valid reference to a handler to be uninstalled by a client application. + :param user_handle: A value specified by an application that can be used for identifying handlers + uniquely in a session for an event. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def unlock(self, session): + """Relinquishes a lock for the specified resource. + + Corresponds to viUnlock function of the VISA library. + + :param session: Unique logical identifier to a session. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def unmap_address(self, session): + """Unmaps memory space previously mapped by map_address(). + + Corresponds to viUnmapAddress function of the VISA library. + + :param session: Unique logical identifier to a session. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def unmap_trigger(self, session, trigger_source, trigger_destination): + """Undo a previous map from the specified trigger source line to the specified destination line. + + Corresponds to viUnmapTrigger function of the VISA library. + + :param session: Unique logical identifier to a session. + :param trigger_source: Source line used in previous map. (Constants.VI_TRIG*) + :param trigger_destination: Destination line used in previous map. (Constants.VI_TRIG*) + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def usb_control_in(self, session, request_type_bitmap_field, request_id, request_value, + index, length=0): + """Performs a USB control pipe transfer from the device. + + Corresponds to viUsbControlIn function of the VISA library. + + :param session: Unique logical identifier to a session. + :param request_type_bitmap_field: bmRequestType parameter of the setup stage of a USB control transfer. + :param request_id: bRequest parameter of the setup stage of a USB control transfer. + :param request_value: wValue parameter of the setup stage of a USB control transfer. + :param index: wIndex parameter of the setup stage of a USB control transfer. + This is usually the index of the interface or endpoint. + :param length: 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. + :return: - The data buffer that receives the data from the optional data stage of the control transfer + - return value of the library call. + :rtype: - bytes + - :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def usb_control_out(self, session, request_type_bitmap_field, request_id, request_value, + index, data=""): + """Performs a USB control pipe transfer to the device. + + Corresponds to viUsbControlOut function of the VISA library. + + :param session: Unique logical identifier to a session. + :param request_type_bitmap_field: bmRequestType parameter of the setup stage of a USB control transfer. + :param request_id: bRequest parameter of the setup stage of a USB control transfer. + :param request_value: wValue parameter of the setup stage of a USB control transfer. + :param index: wIndex parameter of the setup stage of a USB control transfer. + This is usually the index of the interface or endpoint. + :param data: The data buffer that sends the data in the optional data stage of the control transfer. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def vxi_command_query(self, session, mode, command): + """Sends the device a miscellaneous command or query and/or retrieves the response to a previous query. + + Corresponds to viVxiCommandQuery function of the VISA library. + + :param session: Unique logical identifier to a session. + :param mode: Specifies whether to issue a command and/or retrieve a response. (Constants.VI_VXI_CMD*, .VI_VXI_RESP*) + :param command: The miscellaneous command to send. + :return: The response retrieved from the device, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def wait_on_event(self, session, in_event_type, timeout): + """Waits for an occurrence of the specified event for a given session. + + Corresponds to viWaitOnEvent function of the VISA library. + + :param session: Unique logical identifier to a session. + :param in_event_type: Logical identifier of the event(s) to wait for. + :param timeout: 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. + :return: - Logical identifier of the event actually received + - A handle specifying the unique occurrence of an event + - return value of the library call. + :rtype: - eventtype + - event + - :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def write(self, session, data): + """Writes data to device or interface synchronously. + + Corresponds to viWrite function of the VISA library. + + :param session: Unique logical identifier to a session. + :param data: data to be written. + :type data: str + :return: Number of bytes actually transferred, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def write_asynchronously(self, session, data): + """Writes data to device or interface asynchronously. + + Corresponds to viWriteAsync function of the VISA library. + + :param session: Unique logical identifier to a session. + :param data: data to be written. + :return: Job ID of this asynchronous write operation, return value of the library call. + :rtype: jobid, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + def write_from_file(self, session, filename, count): + """Take data from a file and write it out synchronously. + + Corresponds to viWriteFromFile function of the VISA library. + + :param session: Unique logical identifier to a session. + :param filename: Name of file from which data will be read. + :param count: Number of bytes to be written. + :return: Number of bytes actually transferred, return value of the library call. + :rtype: int, :class:`pyvisa.constants.StatusCode` + """ + raise NotImplementedError + + +def list_backends(): + """Return installed backends. + + Backends are installed python packages named pyvisa- where + is the name of the backend. + + :rtype: list + """ + return ['ni'] + [name for (loader, name, ispkg) in pkgutil.iter_modules() + if name.startswith('pyvisa-') and not name.endswith('-script')] + + +#: Maps backend name to VisaLibraryBase derived class +#: dict[str, :class:`pyvisa.highlevel.VisaLibraryBase`] +_WRAPPERS = {} + + +def get_wrapper_class(backend_name): + """Return the WRAPPER_CLASS for a given backend. + + :rtype: pyvisa.highlevel.VisaLibraryBase + """ + try: + return _WRAPPERS[backend_name] + except KeyError: + if backend_name == 'ni': + from .ctwrapper import NIVisaLibrary + _WRAPPERS['ni'] = NIVisaLibrary + return NIVisaLibrary + + try: + pkg = __import__('pyvisa-' + backend_name) + _WRAPPERS[backend_name] = cls = pkg.WRAPPER_CLASS + return cls + except ImportError: + raise ValueError('Wrapper not found: No package named pyvisa-%s' % backend_name) + + +def _get_default_wrapper(): + """Return an available default VISA wrapper as a string ('ni' or 'py'). + + Use NI if the binary is found, else try to use pyvisa-py. + If neither can be found, raise a ValueError. + """ + + from .ctwrapper import NIVisaLibrary + ni_binary_found = bool(NIVisaLibrary.get_library_paths()) + if ni_binary_found: + logger.debug('The NI implementation available') + return 'ni' + else: + logger.debug('Did not find NI 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 NI binary or pyvisa-py.') + + +def open_visa_library(specification): + """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. + """ + + 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.') + + 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: + 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 + + :param visa_library: VisaLibrary Instance, path of the VISA library or VisaLibrary spec string. + (if not given, the default for the platform will be used). + """ + + #: Maps (Interface Type, Resource Class) to Python class encapsulating that resource. + _resource_classes = dict() + + #: Session handler for the resource manager. + _session = None + + @classmethod + def register_resource_class(cls, interface_type, resource_class, python_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)) + cls._resource_classes[(interface_type, resource_class)] = python_class + + def __new__(cls, visa_library=''): + 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 + + logger.debug('Created ResourceManager with session %s', obj.session) + return obj + + @property + def session(self): + """Resource Manager session handle. + + :raises: :class:`pyvisa.errors.InvalidSession` if session is closed. + """ + if self._session is None: + raise errors.InvalidSession() + return self._session + + @session.setter + def session(self, value): + self._session = value + + def __str__(self): + return 'Resource Manager of %s' % self.visalib + + def __repr__(self): + return '' % self.visalib + + def __del__(self): + self.close() + + def ignore_warning(self, *warnings_constants): + """Ignoring warnings context manager for the current resource. + + :param warnings_constants: constants identifying the warnings to ignore. + """ + return self.visalib.ignore_warning(self.session, *warnings_constants) + + @property + def last_status(self): + """Last status code returned for an operation with this Resource Manager + + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return self.visalib.get_last_status_in_session(self.session) + + def close(self): + """Close the resource manager session. + """ + try: + logger.debug('Closing ResourceManager (session: %s)', self.session) + self.visalib.close(self.session) + self.session = None + self.visalib.resource_manager = None + except errors.InvalidSession: + pass + + def list_resources(self, query='?*::INSTR'): + """Returns a tuple of all connected devices matching query. + + note: 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'. + + :param query: a VISA Resource Regular Expression used to match devices. + + """ + + return self.visalib.list_resources(self.session, query) + + def list_resources_info(self, query='?*::INSTR'): + """Returns a dictionary mapping resource names to resource extended + information of all connected devices matching query. + + For details of the VISA Resource Regular Expression syntax used in query, + refer to list_resources(). + + :param query: a VISA Resource Regular Expression used to match devices. + :return: Mapping of resource name to ResourceInfo + :rtype: dict[str, :class:`pyvisa.highlevel.ResourceInfo`] + """ + + return dict((resource, self.resource_info(resource)) + for resource in self.list_resources(query)) + + def resource_info(self, resource_name, extended=True): + """Get the (extended) information of a particular resource. + + :param resource_name: Unique symbolic name of a resource. + + :rtype: :class:`pyvisa.highlevel.ResourceInfo` + """ + + 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, + access_mode=constants.AccessModes.no_lock, + open_timeout=constants.VI_TMO_IMMEDIATE): + """Open the specified resource without wrapping into a class + + :param resource_name: name or alias of the resource to open. + :param access_mode: access mode. + :type access_mode: :class:`pyvisa.constants.AccessModes` + :param open_timeout: time out to open. + + :return: Unique logical identifier reference to a session. + """ + return self.visalib.open(self.session, resource_name, access_mode, open_timeout) + + def open_resource(self, resource_name, + access_mode=constants.AccessModes.no_lock, + open_timeout=constants.VI_TMO_IMMEDIATE, + resource_pyclass=None, + **kwargs): + """Return an instrument for the resource name. + + :param resource_name: name or alias of the resource to open. + :param access_mode: access mode. + :type access_mode: :class:`pyvisa.constants.AccessModes` + :param open_timeout: time out to open. + :param resource_pyclass: resource python class to use to instantiate the Resource. + Defaults to None: select based on the resource name. + :param kwargs: keyword arguments to be used to change instrument attributes + after construction. + + :rtype: :class:`pyvisa.resources.Resource` + """ + + if resource_pyclass is None: + info = self.resource_info(resource_name, extended=True) + + try: + resource_pyclass = self._resource_classes[(info.interface_type, info.resource_class)] + 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) + + return res + + #: For backwards compatibility + get_instrument = open_resource diff --git a/pyvisa/resources/__init__.py b/pyvisa/resources/__init__.py new file mode 100644 index 0000000..a18b91c --- /dev/null +++ b/pyvisa/resources/__init__.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.resources + ~~~~~~~~~~~~~~~~ + + High level wrappers for resources. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +from .resource import Resource + +from .gpib import GPIBInterface +from .vxi import VXIBackplane +from .vxi import VXIInstrument + +from .messagebased import MessageBasedResource +from .gpib import GPIBInstrument +from .tcpip import TCPIPInstrument +from .tcpip import TCPIPSocket +from .serial import SerialInstrument +from .usb import USBRaw +from .usb import USBInstrument + +from .registerbased import RegisterBasedResource +from .firewire import FirewireInstrument +from .pxi import PXIMemory +from .pxi import PXIInstrument +from .vxi import VXIMemory + +__all__ = ['Resource', 'MessageBasedResource', 'RegisterBasedResource', + 'GPIBInterface', 'VXIBackplane', 'VXIInstrument', + 'GPIBInstrument', 'TCPIPInstrument', 'TCPIPSocket', 'SerialInstrument', 'USBRaw', 'USBInstrument', + 'FirewireInstrument', 'PXIMemory', 'PXIInstrument', 'VXIMemory'] diff --git a/pyvisa/resources/firewire.py b/pyvisa/resources/firewire.py new file mode 100644 index 0000000..3fd5502 --- /dev/null +++ b/pyvisa/resources/firewire.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.resources.vxi + ~~~~~~~~~~~~~~~~~~~~ + + High level wrapper for VXI resources. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +from .. import constants + +from .registerbased import RegisterBasedResource + + +@RegisterBasedResource.register(constants.InterfaceType.firewire, 'INSTR') +class FirewireInstrument(RegisterBasedResource): + """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`. + """ diff --git a/pyvisa/resources/gpib.py b/pyvisa/resources/gpib.py new file mode 100644 index 0000000..e601cdf --- /dev/null +++ b/pyvisa/resources/gpib.py @@ -0,0 +1,148 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.resources.gpib + ~~~~~~~~~~~~~~~~~~~~~ + + High level wrapper for GPIB resources. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import time + +from .. import constants +from .resource import Resource +from .messagebased import MessageBasedResource, ControlRenMixin + + +class _GPIBMixin(ControlRenMixin): + """Common attributes and methods of GPIB Instr and Interface. + """ + + def send_command(self, data): + """Write GPIB command bytes on the bus. + + Corresponds to viGpibCommand function of the VISA library. + + :param data: data tor write. + :type data: bytes + :return: Number of written bytes, return value of the library call. + :rtype: int, VISAStatus + """ + return self.visalib.gpib_command(self.session, data) + + def control_atn(self, mode): + """Specifies the state of the ATN line and the local active controller state. + + Corresponds to viGpibControlATN function of the VISA library. + + :param mode: Specifies the state of the ATN line and optionally the local active controller state. + (Constants.GPIB_ATN*) + :return: return value of the library call. + :rtype: VISAStatus + """ + return self.visalib.gpib_control_atn(self.session, mode) + + def pass_control(self, primary_address, secondary_address): + """Tell the GPIB device at the specified address to become controller in charge (CIC). + + Corresponds to viGpibPassControl function of the VISA library. + + :param primary_address: Primary address of the GPIB device to which you want to pass control. + :param secondary_address: 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. + :return: return value of the library call. + :rtype: VISAStatus + """ + return self.visalib.gpib_pass_control(self.session, primary_address, secondary_address) + + def send_ifc(self): + """Pulse the interface clear line (IFC) for at least 100 microseconds. + + Corresponds to viGpibSendIFC function of the VISA library. + + :return: return value of the library call. + :rtype: VISAStatus + """ + 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`. + """ + + def wait_for_srq(self, timeout=25000): + """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. + + :param timeout: the maximum waiting time in milliseconds. + Defaul: 25000 (milliseconds). + None means waiting forever if necessary. + """ + self.enable_event(constants.VI_EVENT_SERVICE_REQ, constants.VI_QUEUE) + + if timeout and not(0 <= timeout <= 4294967295): + raise ValueError("timeout value is invalid") + + starting_time = time.clock() + + while True: + if timeout is None: + adjusted_timeout = constants.VI_TMO_INFINITE + else: + adjusted_timeout = int((starting_time + timeout/1e3 - time.clock())*1e3) + if adjusted_timeout < 0: + adjusted_timeout = 0 + + self.wait_on_event(constants.VI_EVENT_SERVICE_REQ, adjusted_timeout) + if self.stb & 0x40: + break + + self.discard_events(constants.VI_EVENT_SERVICE_REQ, constants.VI_QUEUE) + + +@Resource.register(constants.InterfaceType.gpib, 'INTFC') +class GPIBInterface(_GPIBMixin, Resource): + """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`. + """ + + def group_execute_trigger(self, *resources): + + 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)) diff --git a/pyvisa/resources/messagebased.py b/pyvisa/resources/messagebased.py new file mode 100644 index 0000000..ca92fb1 --- /dev/null +++ b/pyvisa/resources/messagebased.py @@ -0,0 +1,715 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.resources.messagebased + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + High level wrapper for MessageBased Instruments. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import (division, unicode_literals, print_function, + absolute_import) + +import contextlib +import time +import warnings + +from .. import logger +from .. import constants +from .. import errors +from .. import util + +from .resource import Resource + + +class ValuesFormat(object): + """Options for reading values. + """ + __slots__ = ('is_binary', 'container', + 'datatype', 'is_big_endian', + 'converter', 'separator', 'header_fmt') + + def __init__(self): + self.is_binary = True + self.datatype = 'f' + self.is_big_endian = False + self.container = list + self.converter = 'f' + self.separator = ',' + self.header_fmt = 'ieee' + + def use_ascii(self, converter, separator, container=list): + self.converter = converter + self.separator = separator + self.container = container + self.is_binary = False + + def use_binary(self, datatype, is_big_endian, container=list, + header_fmt='ieee'): + self.datatype = datatype + self.is_big_endian = is_big_endian + self.container = container + self.is_binary = True + self.header_fmt = header_fmt + + +class ControlRenMixin(object): + """Common control_ren method of some messaged based resources. + + """ + # 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): + """Controls the state of the GPIB Remote Enable (REN) interface line, + and optionally the remote/local state of the device. + + Corresponds to viGpibControlREN function of the VISA library. + + :param mode: Specifies the state of the REN line and optionally the + device remote/local state. (Constants.GPIB_REN*) + :return: return value of the library call. + :rtype: VISAStatus + """ + return self.visalib.gpib_control_ren(self.session, mode) + + +class MessageBasedResource(Resource): + """Base class for resources that use message based communication. + """ + + CR = '\r' + LF = '\n' + + _read_termination = None + _write_termination = CR + LF + _encoding = 'ascii' + + chunk_size = 20 * 1024 + query_delay = 0.0 + + _values_format = None + + def __init__(self, *args, **kwargs): + self._values_format = ValuesFormat() + super(MessageBasedResource, self).__init__(*args, **kwargs) + + # This is done for backwards compatibility but will be removed in 1.10 + @property + def values_format(self): + warnings.warn('values_format is deprecated and will be removed in ' + '1.10', FutureWarning) + return self._values_format + + @values_format.setter + def values_format(self, fmt): + warnings.warn('values_format is deprecated and will be removed in ' + '1.10', FutureWarning) + self._values_format.is_binary = not (fmt & 0x01 == 0) + if fmt & 0x03 == 1: # single + self._values_format.datatype = 'f' + elif fmt & 0x03 == 3: # double: + self._values_format.datatype = 'd' + else: + raise ValueError("unknown data values fmt requested") + + self._values_format.is_big_endian = fmt & 0x04 + + #### + + @property + def ask_delay(self): + """An alias for query_delay kept for backwards compatibility. + """ + warnings.warn('ask_delay is deprecated and will be removed in ' + '1.10, use query_delay instead', FutureWarning) + return self.query_delay + + @ask_delay.setter + def ask_delay(self, value): + warnings.warn('ask_delay is deprecated and will be removed in ' + '1.10, use query_delay instead', FutureWarning) + self.query_delay = value + + @property + def encoding(self): + """Encoding used for read and write operations. + """ + return self._encoding + + @encoding.setter + def encoding(self, encoding): + # Test that the encoding specified makes sense. + 'test encoding'.encode(encoding).decode(encoding) + self._encoding = encoding + + @property + def read_termination(self): + """Read termination character. + """ + return self._read_termination + + @read_termination.setter + def read_termination(self, value): + + 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.VI_ATTR_TERMCHAR, ord(last_char)) + self.set_visa_attribute(constants.VI_ATTR_TERMCHAR_EN, + 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.VI_ATTR_TERMCHAR, ord(self.LF)) + self.set_visa_attribute(constants.VI_ATTR_TERMCHAR_EN, + constants.VI_FALSE) + + self._read_termination = value + + @property + def write_termination(self): + """Writer termination character. + """ + return self._write_termination + + @write_termination.setter + def write_termination(self, value): + self._write_termination = value + + def write_raw(self, message): + """Write a byte message to the device. + + :param message: the message to be sent. + :type message: bytes + :return: number of bytes written. + :rtype: int + """ + return self.visalib.write(self.session, message) + + def write(self, message, termination=None, encoding=None): + """Write a string message to the device. + + The write_termination is always appended to it. + + :param message: the message to be sent. + :type message: unicode (Py2) or str (Py3) + :return: number of bytes written. + :rtype: int + """ + + 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, values, converter='f', separator=',', + termination=None, encoding=None): + """Write a string message to the device followed by values in ascii + format. + + The write_termination is always appended to it. + + :param message: the message to be sent. + :type message: unicode (Py2) or str (Py3) + :param values: data to be writen to the device. + :param converter: function used to convert each value. + String formatting codes are also accepted. + Defaults to str. + :type converter: callable | str + :param separator: a callable that join the values in a single str. + If a str is given, separator.join(values) is used. + :type: separator: (collections.Iterable[T]) -> str | str + :return: number of bytes written. + :rtype: int + """ + + 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) + + message = message.encode(enco) + block.encode(enco) + + if term: + message += term.encode(enco) + + count = self.write_raw(message) + + return count + + def write_binary_values(self, message, values, datatype='f', + is_big_endian=False, termination=None, + encoding=None): + """Write a string message to the device followed by values in binary + format. + + The write_termination is always appended to it. + + :param message: the message to be sent. + :type message: unicode (Py2) or str (Py3) + :param values: data to be writen to the device. + :param datatype: the format string for a single element. See struct + module. + :param is_big_endian: boolean indicating endianess. + :return: number of bytes written. + :rtype: int + """ + 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_ieee_block(values, datatype, is_big_endian) + + message = message.encode(enco) + block + + if term: + message += term.encode(enco) + + count = self.write_raw(message) + + return count + + def write_values(self, message, values, termination=None, encoding=None): + warnings.warn('write_values is deprecated and will be removed in ' + '1.10, use write_ascii_values or write_binary_values ' + 'instead.', FutureWarning) + vf = self.values_format + + if vf.is_binary: + return self.write_binary_values(message, values, vf.datatype, + vf.is_big_endian, termination, + encoding) + + return self.write_ascii_values(message, values, vf.converter, + vf.separator, termination, encoding) + + def read_bytes(self, count, chunk_size=None, break_on_termchar=False): + """Read a certain number of bytes from the instrument. + + :param count: The number of bytes to read from the instrument. + :type count: int + :param chunk_size: The chunk size to use to perform the reading. + :type chunk_size: int + :param break_on_termchar: Should the reading stop when a termination + character is encountered. + :type brak_on_termchar: bool + + :rtype: bytes + + """ + chunk_size = chunk_size or self.chunk_size + ret = bytearray() + left_to_read = count + termchar_read = constants.StatusCode.success_termination_character_read + + with self.ignore_warning(constants.VI_SUCCESS_DEV_NPRESENT, + constants.VI_SUCCESS_MAX_CNT): + 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 == 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=None): + """Read the unmodified string sent from the instrument to the computer. + + In contrast to read(), no termination characters are stripped. + + :param size: The chunk size to use when reading the data. + + :rtype: bytes + """ + return bytes(self._read_raw(size)) + + def _read_raw(self, size=None): + """Read the unmodified string sent from the instrument to the computer. + + In contrast to read(), no termination characters are stripped. + + :param size: The chunk size to use when reading the data. + + :rtype: bytearray + """ + 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.VI_SUCCESS_DEV_NPRESENT, + constants.VI_SUCCESS_MAX_CNT): + 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=None, encoding=None): + """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. + + All line-ending characters are stripped from the end of the string. + + :rtype: str + """ + 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[:-len(termination)] + + def read_ascii_values(self, converter='f', separator=',', container=list, + delay=None): + """Read values from the device in ascii format returning an iterable of + values. + + :param delay: delay in seconds between write and read operations. + if None, defaults to self.query_delay + :param converter: function used to convert each element. + Defaults to float + :type converter: callable + :param separator: a callable that split the str into individual + elements. If a str is given, data.split(separator) is + used. + :type: separator: (str) -> collections.Iterable[int] | str + :param container: container type to use for the output data. + :returns: the answer from the device. + :rtype: list + + """ + # 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='f', is_big_endian=False, + container=list, header_fmt='ieee', + expect_termination=True): + """Read values from the device in binary format returning an iterable + of values. + + :param datatype: the format string for a single element. See struct + module. + :param is_big_endian: boolean indicating endianess. + Defaults to False. + :param container: container type to use for the output data. + :param header_fmt: format of the header prefixing the data. Possible + values are: 'ieee', 'hp', 'empty' + :param expect_termination: when set to False, the expected length of + the binary values block does not account + for the final termination character (the + read termination) + :returns: the answer from the device. + :rtype: type(container) + + """ + block = self._read_raw() + expected_length = 0 + + if header_fmt == 'ieee': + offset, data_length = util.parse_ieee_block_header(block) + expected_length = offset + data_length + elif header_fmt == 'hp': + offset, data_length = util.parse_hp_block_header(block, + is_big_endian) + expected_length = offset + data_length + + if expect_termination and self._read_termination is not None: + expected_length += len(self._read_termination) + + while len(block) < expected_length: + block.extend(self._read_raw()) + + try: + if header_fmt == 'ieee': + return util.from_ieee_block(block, datatype, is_big_endian, + container) + elif header_fmt == 'hp': + return util.from_hp_block(block, datatype, is_big_endian, + container) + elif header_fmt == 'empty': + return util.from_binary_block(block, 0, None, datatype, + is_big_endian, container) + else: + raise ValueError('Unsupported binary block format.') + except ValueError as e: + raise errors.InvalidBinaryFormat(e.args) + + def read_values(self, fmt=None, container=list): + """Read a list of floating point values from the device. + + :param fmt: the format of the values. If given, it overrides + the class attribute "values_format". Possible values are bitwise + disjunctions of the above constants ascii, single, double, and + big_endian. Default is ascii. + :param container: the output datatype + + :return: the list of read values + :rtype: list + """ + warnings.warn('read_values is deprecated and will be removed in ' + '1.10, use read_ascii_values or read_binary_values ' + 'instead.', FutureWarning) + if not fmt: + vf = self.values_format + if not vf.is_binary: + return util.from_ascii_block(self.read(), container) + data = self._read_raw() + try: + return util.parse_binary(data, vf.is_big_endian, + vf.datatype == 'f') + except ValueError as e: + try: + msg = e.args[0] + except IndexError: + msg = '' + raise errors.InvalidBinaryFormat(msg) + + if fmt & 0x01 == 0: # ascii + return util.from_ascii_block(self.read()) + + data = self._read_raw() + + try: + if fmt & 0x03 == 1: # single + is_single = True + elif fmt & 0x03 == 3: # double: + is_single = False + else: + raise ValueError("unknown data values fmt requested") + + is_big_endian = fmt & 0x04 # big endian + return util.parse_binary(data, is_big_endian, is_single) + except ValueError as e: + raise errors.InvalidBinaryFormat(e.args) + + def query(self, message, delay=None): + """A combination of write(message) and read() + + :param message: the message to send. + :type message: str + :param delay: delay in seconds between write and read operations. + if None, defaults to self.query_delay + :returns: the answer from the device. + :rtype: str + """ + + self.write(message) + + delay = self.query_delay if delay is None else delay + + if delay > 0.0: + time.sleep(delay) + return self.read() + + def ask(self, message, delay=None): + warnings.warn('ask is deprecated and will be removed in ' + '1.10, use query instead.', FutureWarning) + return self.query(message, delay) + + def query_values(self, message, delay=None): + """Query the device for values returning an iterable of values. + + The datatype expected is obtained from `values_format` + + :param message: the message to send. + :type message: str + :param delay: delay in seconds between write and read operations. + if None, defaults to self.query_delay + :returns: the answer from the device. + :rtype: list + """ + warnings.warn('query_values is deprecated and will be removed in ' + '1.10, use query_ascii_values or quey_binary_values ' + 'instead.', FutureWarning) + vf = self.values_format + + if vf.is_binary: + return self.query_binary_values(message, vf.datatype, + vf.is_big_endian, vf.container, + delay, vf.header_fmt) + + return self.query_ascii_values(message, vf.converter, vf.separator, + vf.container, delay) + + def query_ascii_values(self, message, converter='f', separator=',', + container=list, delay=None): + """Query the device for values in ascii format returning an iterable of + values. + + :param message: the message to send. + :type message: str + :param delay: delay in seconds between write and read operations. + if None, defaults to self.query_delay + :param converter: function used to convert each element. + Defaults to float + :type converter: callable + :param separator: a callable that split the str into individual + elements. If a str is given, data.split(separator) is + used. + :type: separator: (str) -> collections.Iterable[int] | str + :param container: container type to use for the output data. + :returns: the answer from the device. + :rtype: list + """ + + 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, + delay) + + def query_binary_values(self, message, datatype='f', is_big_endian=False, + container=list, delay=None, header_fmt='ieee', + expect_termination=True): + """Query the device for values in binary format returning an iterable + of values. + + :param message: the message to send to the instrument. + :param datatype: the format string for a single element. See struct + module. + :param is_big_endian: boolean indicating endianess. + Defaults to False. + :param container: container type to use for the output data. + :param delay: delay in seconds between write and read operations. + if None, defaults to self.query_delay + :param expect_termination: when set to False, the expected length of + the binary values block does not account + for the final termination character (the + read termination) + :returns: the answer from the device. + :rtype: list + """ + 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) + + def ask_for_values(self, message, fmt=None, delay=None): + """A combination of write(message) and read_values() + + :param message: the message to send. + :type message: str + :param delay: delay in seconds between write and read operations. + if None, defaults to self.query_delay + :returns: the answer from the device. + :rtype: list + """ + warnings.warn('ask_values is deprecated and will be removed in ' + '1.10, use query_ascii_values or quey_binary_values ' + 'instead.', FutureWarning) + self.write(message) + if delay is None: + delay = self.query_delay + if delay > 0.0: + time.sleep(delay) + return self.read_values(fmt) + + def assert_trigger(self): + """Sends a software trigger to the device. + """ + + self.visalib.assert_trigger(self.session, + constants.VI_TRIG_PROT_DEFAULT) + + @property + def stb(self): + """Service request status register.""" + + return self.read_stb() + + def read_stb(self): + """Service request status register. + """ + value, retcode = self.visalib.read_stb(self.session) + return value + + @contextlib.contextmanager + def read_termination_context(self, new_termination): + term = self.get_visa_attribute(constants.VI_ATTR_TERMCHAR) + self.set_visa_attribute(constants.VI_ATTR_TERMCHAR, + ord(new_termination[-1])) + yield + self.set_visa_attribute(constants.VI_ATTR_TERMCHAR, term) + + +# Rohde and Schwarz Device via Passport. Not sure which Resource should be. +MessageBasedResource.register(constants.InterfaceType.rsnrp, + 'INSTR')(MessageBasedResource) diff --git a/pyvisa/resources/pxi.py b/pyvisa/resources/pxi.py new file mode 100644 index 0000000..cfaef6e --- /dev/null +++ b/pyvisa/resources/pxi.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.resources.pxi + ~~~~~~~~~~~~~~~~~~~~ + + High level wrapper for pxi resources. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +from .. import constants + +from .resource import Resource +from .registerbased import RegisterBasedResource + + +@Resource.register(constants.InterfaceType.pxi, 'INSTR') +class PXIInstrument(RegisterBasedResource): + """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`. + """ + + +@Resource.register(constants.InterfaceType.pxi, 'MEMACC') +class PXIMemory(RegisterBasedResource): + """Communicates with to devices of type PXI[interface]::MEMACC + + Do not instantiate directly, use :meth:`pyvisa.highlevel.ResourceManager.open_resource`. + """ diff --git a/pyvisa/resources/registerbased.py b/pyvisa/resources/registerbased.py new file mode 100644 index 0000000..2b5eb51 --- /dev/null +++ b/pyvisa/resources/registerbased.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.resources.registerbased + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + High level wrapper for RegisterBased Instruments. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +from .resource import Resource + + +class RegisterBasedResource(Resource): + """Base class for resources that use register based communication. + """ + + def read_memory(self, space, offset, width, extended=False): + """Reads in an 8-bit, 16-bit, 32-bit, or 64-bit value from the specified memory space and offset. + + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param width: Number of bits to read. + :param extended: Use 64 bits offset independent of the platform. + :return: Data read from memory. + + Corresponds to viIn* functions of the visa library. + """ + return self.visalib.read_memory(self.session, space, offset, width, extended) + + def write_memory(self, space, offset, data, width, extended=False): + """Write in an 8-bit, 16-bit, 32-bit, value to the specified memory space and offset. + + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param data: Data to write to bus. + :param width: Number of bits to read. + :param extended: Use 64 bits offset independent of the platform. + + Corresponds to viOut* functions of the visa library. + """ + return self.visalib.write_memory(self.session, space, offset, data, width, extended) + + def move_in(self, space, offset, length, width, extended=False): + """Moves a block of data to local memory from the specified address space and offset. + + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param width: Number of bits to read per element. + :param extended: Use 64 bits offset independent of the platform. + """ + return self.visalib.move_in(self.session, space, offset, length, width, extended) + + def move_out(self, space, offset, length, data, width, extended=False): + """Moves a block of data from local memory to the specified address space and offset. + + :param space: Specifies the address space. (Constants.*SPACE*) + :param offset: Offset (in bytes) of the address or register from which to read. + :param length: Number of elements to transfer, where the data width of the elements to transfer + is identical to the source data width. + :param data: Data to write to bus. + :param width: Number of bits to read per element. + :param extended: Use 64 bits offset independent of the platform. + """ + return self.visalib.move_out(space, offset, length, data, width, extended) diff --git a/pyvisa/resources/resource.py b/pyvisa/resources/resource.py new file mode 100644 index 0000000..46c4963 --- /dev/null +++ b/pyvisa/resources/resource.py @@ -0,0 +1,405 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.resources.resource + ~~~~~~~~~~~~~~~~~~~~~~~~~ + + High level wrapper for a Resource. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import contextlib +import copy +import math +import time + +from .. import constants +from .. import errors +from .. import logger +from .. import highlevel +from .. import attributes + + +class WaitResponse(object): + """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 be + recorded as None, otherwise it records the proper EventType enum. + """ + def __init__(self, event_type, context, ret, visalib, timed_out=False): + if event_type == 0: + self.event_type = None + else: + self.event_type = constants.EventType(event_type) + self.context = context + self.ret = ret + self._visalib = visalib + self.timed_out = timed_out + + def __del__(self): + if self.context != None: + self._visalib.close(self.context) + + +class Resource(object): + """Base class for resources. + + Do not instantiate directly, use :meth:`pyvisa.highlevel.ResourceManager.open_resource`. + + :param resource_manager: A resource manager instance. + :param resource_name: the VISA name for the resource (eg. "GPIB::10") + """ + + @classmethod + def register(cls, interface_type, resource_class): + def _internal(python_class): + highlevel.ResourceManager.register_resource_class(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 list and extended it. + attrs = copy.copy(getattr(python_class, 'visa_attributes_classes', [])) + + for attr in attributes.AttributesPerResource[(interface_type, resource_class)]: + attrs.append(attr) + if not hasattr(python_class, attr.py_name) and attr.py_name != '': + setattr(python_class, attr.py_name, attr()) + for attr in attributes.AttributesPerResource[attributes.AllSessionTypes]: + attrs.append(attr) + if not hasattr(python_class, attr.py_name) and attr.py_name != '': + setattr(python_class, attr.py_name, attr()) + + setattr(python_class, 'visa_attributes_classes', attrs) + return python_class + return _internal + + def __init__(self, resource_manager, resource_name): + self._resource_manager = resource_manager + self.visalib = self._resource_manager.visalib + 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 = None + + @property + def session(self): + """Resource session handle. + + :raises: :class:`pyvisa.errors.InvalidSession` if session is closed. + """ + if self._session is None: + raise errors.InvalidSession() + return self._session + + @session.setter + def session(self, value): + self._session = value + + def __del__(self): + self.close() + + def __str__(self): + return "%s at %s" % (self.__class__.__name__, self.resource_name) + + def __repr__(self): + return "<%r(%r)>" % (self.__class__.__name__, self.resource_name) + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + @property + def last_status(self): + """Last status code for this session. + + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return self.visalib.get_last_status_in_session(self.session) + + def _cleanup_timeout(self, timeout): + 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 + + @property + def timeout(self): + """The timeout in milliseconds for all resource I/O operations. + + 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 + + """ + timeout = self.get_visa_attribute(constants.VI_ATTR_TMO_VALUE) + if timeout == constants.VI_TMO_INFINITE: + return float('+inf') + return timeout + + @timeout.setter + def timeout(self, timeout): + timeout = self._cleanup_timeout(timeout) + self.set_visa_attribute(constants.VI_ATTR_TMO_VALUE, timeout) + + @timeout.deleter + def timeout(self): + self.set_visa_attribute(constants.VI_ATTR_TMO_VALUE, constants.VI_TMO_INFINITE) + + @property + def resource_info(self): + """Get the extended information of this resource. + + :param resource_name: Unique symbolic name of a resource. + + :rtype: :class:`pyvisa.highlevel.ResourceInfo` + """ + return self.visalib.parse_resource_extended(self._resource_manager.session, self.resource_name) + + @property + def interface_type(self): + """The interface type of the resource as a number. + """ + return self.visalib.parse_resource(self._resource_manager.session, + self.resource_name)[0].interface_type + + def ignore_warning(self, *warnings_constants): + """Ignoring warnings context manager for the current resource. + + :param warnings_constants: constants identifying the warnings to ignore. + """ + return self.visalib.ignore_warning(self.session, *warnings_constants) + + def open(self, access_mode=constants.AccessModes.no_lock, open_timeout=5000): + """Opens a session to the specified resource. + + :param access_mode: Specifies the mode by which the resource is to be accessed. + :type access_mode: :class:`pyvisa.constants.AccessModes` + :param open_timeout: Milliseconds before the open operation times out. + :type open_timeout: int + """ + + logger.debug('%s - opening ...', self._resource_name, extra=self._logging_extra) + with self._resource_manager.ignore_warning(constants.VI_SUCCESS_DEV_NPRESENT): + self.session, status = self._resource_manager.open_bare_resource(self._resource_name, access_mode, open_timeout) + + if status == constants.VI_SUCCESS_DEV_NPRESENT: + # 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.VI_ERROR_NLISTENERS: + 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): + """Called just before closing an instrument. + """ + self.__switch_events_off() + + def close(self): + """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) + self.session = None + except errors.InvalidSession: + pass + + def __switch_events_off(self): + self.disable_event(constants.VI_ALL_ENABLED_EVENTS, constants.VI_ALL_MECH) + self.discard_events(constants.VI_ALL_ENABLED_EVENTS, constants.VI_ALL_MECH) + self.visalib.uninstall_all_visa_handlers(self.session) + + def get_visa_attribute(self, name): + """Retrieves the state of an attribute in this resource. + + :param name: Resource attribute for which the state query is made (see Attributes.*) + :return: The state of the queried attribute for a specified resource. + :rtype: unicode (Py2) or str (Py3), list or other type + """ + return self.visalib.get_attribute(self.session, name)[0] + + def set_visa_attribute(self, name, state): + """Sets the state of an attribute. + + :param name: Attribute for which the state is to be modified. (Attributes.*) + :param state: The state of the attribute to be set for the specified object. + :return: return value of the library call. + :rtype: :class:`pyvisa.constants.StatusCode` + """ + return self.visalib.set_attribute(self.session, name, state) + + def clear(self): + """Clears this resource + """ + self.visalib.clear(self.session) + + def install_handler(self, event_type, handler, user_handle=None): + """Installs handlers for event callbacks in this resource. + + :param event_type: Logical event identifier. + :param handler: Interpreted as a valid reference to a handler to be installed by a client application. + :param user_handle: A value specified by an application that can be used for identifying handlers + uniquely for an event type. + :returns: user handle (a ctypes object) + """ + + return self.visalib.install_visa_handler(self.session, event_type, handler, user_handle) + + def uninstall_handler(self, event_type, handler, user_handle=None): + """Uninstalls handlers for events in this resource. + + :param event_type: Logical event identifier. + :param handler: Interpreted as a valid reference to a handler to be uninstalled by a client application. + :param user_handle: The user handle (ctypes object or None) returned by install_handler. + """ + + self.visalib.uninstall_visa_handler(self.session, event_type, handler, user_handle) + + def disable_event(self, event_type, mechanism): + """Disables notification of the specified event type(s) via the specified mechanism(s). + + :param event_type: Logical event identifier. + :param mechanism: Specifies event handling mechanisms to be disabled. + (Constants.VI_QUEUE, .VI_HNDLR, .VI_SUSPEND_HNDLR, .VI_ALL_MECH) + """ + self.visalib.disable_event(self.session, event_type, mechanism) + + def discard_events(self, event_type, mechanism): + """Discards event occurrences for specified event types and mechanisms in this resource. + + :param event_type: Logical event identifier. + :param mechanism: Specifies event handling mechanisms to be dicarded. + (Constants.VI_QUEUE, .VI_HNDLR, .VI_SUSPEND_HNDLR, .VI_ALL_MECH) + """ + self.visalib.discard_events(self.session, event_type, mechanism) + + def enable_event(self, event_type, mechanism, context=None): + """Enable event occurrences for specified event types and mechanisms in this resource. + + :param event_type: Logical event identifier. + :param mechanism: Specifies event handling mechanisms to be enabled. + (Constants.VI_QUEUE, .VI_HNDLR, .VI_SUSPEND_HNDLR) + :param context: Not currently used, leave as None. + """ + self.visalib.enable_event(self.session, event_type, mechanism, context) + + def wait_on_event(self, in_event_type, timeout, capture_timeout=False): + """Waits for an occurrence of the specified event in this resource. + + :param in_event_type: Logical identifier of the event(s) to wait for. + :param timeout: 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. + :param capture_timeout: When True will not produce a VisaIOError(VI_ERROR_TMO) but + instead return a WaitResponse with timed_out=True + :return: A 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, exc.error_code, self.visalib, timed_out=True) + raise + return WaitResponse(event_type, context, ret, self.visalib) + + def lock(self, timeout='default', requested_key=None): + """Establish a shared lock to the resource. + + :param timeout: Absolute time period (in milliseconds) that a resource + waits to get unlocked by the locking session before + returning an error. (Defaults to self.timeout) + :param requested_key: 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: A new shared access key if requested_key is None, + otherwise, same value as the requested_key + """ + timeout = self.timeout if timeout == 'default' else timeout + timeout = self._cleanup_timeout(timeout) + return self.visalib.lock(self.session, constants.AccessModes.shared_lock, timeout, requested_key)[0] + + def lock_excl(self, timeout='default'): + """Establish an exclusive lock to the resource. + + :param timeout: Absolute time period (in milliseconds) that a resource + waits to get unlocked by the locking session before + returning an error. (Defaults to self.timeout) + """ + timeout = self.timeout if timeout == 'default' else timeout + timeout = self._cleanup_timeout(timeout) + self.visalib.lock(self.session, constants.AccessModes.exclusive_lock, timeout, None) + + def unlock(self): + """Relinquishes a lock for the specified resource. + """ + self.visalib.unlock(self.session) + + @contextlib.contextmanager + def lock_context(self, timeout='default', requested_key='exclusive'): + """A context that locks + + :param timeout: Absolute time period (in milliseconds) that a resource + waits to get unlocked by the locking session before + returning an error. (Defaults to self.timeout) + :param requested_key: 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. + The returned context is 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) diff --git a/pyvisa/resources/serial.py b/pyvisa/resources/serial.py new file mode 100644 index 0000000..0b32289 --- /dev/null +++ b/pyvisa/resources/serial.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.resources.serial + ~~~~~~~~~~~~~~~~~~~~~~~ + + High level wrapper for Serial resources. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +from .. import constants + +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`. + """ + + def flush(self, mask): + """Manually clears the specified buffers and cause the buffer data + to be written to the device. + + :param mask: Specifies the action to be taken with flushing the buffer. + (Constants.READ*, .WRITE*, .IO*) + """ + self.visalib.flush(self.session, mask) diff --git a/pyvisa/resources/tcpip.py b/pyvisa/resources/tcpip.py new file mode 100644 index 0000000..87f9fc6 --- /dev/null +++ b/pyvisa/resources/tcpip.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.resources.tcpip + ~~~~~~~~~~~~~~~~~~~~~~ + + High level wrapper for TCPIP resources. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +from .. import constants + +from .resource import Resource +from .messagebased import MessageBasedResource, ControlRenMixin + + +@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`. + """ + + +@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`. + """ diff --git a/pyvisa/resources/usb.py b/pyvisa/resources/usb.py new file mode 100644 index 0000000..21e5025 --- /dev/null +++ b/pyvisa/resources/usb.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.resources.usb + ~~~~~~~~~~~~~~~~~~~~ + + High level wrapper for USB resources. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +from .. import constants +from .messagebased import MessageBasedResource, ControlRenMixin + + +@MessageBasedResource.register(constants.InterfaceType.usb, 'INSTR') +class USBInstrument(ControlRenMixin, MessageBasedResource): + """Communicates with devices of type 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`. + """ + + def control_in(self, request_type_bitmap_field, request_id, request_value, index, length=0): + """Performs a USB control pipe transfer from the device. + + :param request_type_bitmap_field: bmRequestType parameter of the setup stage of a USB control transfer. + :param request_id: bRequest parameter of the setup stage of a USB control transfer. + :param request_value: wValue parameter of the setup stage of a USB control transfer. + :param index: wIndex parameter of the setup stage of a USB control transfer. + This is usually the index of the interface or endpoint. + :param length: 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. + :return: The data buffer that receives the data from the optional data stage of the control transfer. + :rtype: bytes + """ + return self.visalib.usb_control_in(self.session, request_type_bitmap_field, + request_id, request_value, index, length) + + def usb_control_out(self, request_type_bitmap_field, request_id, request_value, index, data=""): + """Performs a USB control pipe transfer to the device. + + :param request_type_bitmap_field: bmRequestType parameter of the setup stage of a USB control transfer. + :param request_id: bRequest parameter of the setup stage of a USB control transfer. + :param request_value: wValue parameter of the setup stage of a USB control transfer. + :param index: wIndex parameter of the setup stage of a USB control transfer. + This is usually the index of the interface or endpoint. + :param data: The data buffer that sends the data in the optional data stage of the control transfer. + """ + return self.visalib.usb_control_out(request_type_bitmap_field, request_id, request_value, index, data) + + +@MessageBasedResource.register(constants.InterfaceType.usb, 'RAW') +class USBRaw(MessageBasedResource): + """Communicates with to devices of type 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`. + """ diff --git a/pyvisa/resources/vxi.py b/pyvisa/resources/vxi.py new file mode 100644 index 0000000..e84e8a8 --- /dev/null +++ b/pyvisa/resources/vxi.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.resources.vxi + ~~~~~~~~~~~~~~~~~~~~ + + High level wrapper for VXI resources. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +from .. import constants + +from .resource import Resource +from .registerbased import RegisterBasedResource + + +@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`. + """ + + +@Resource.register(constants.InterfaceType.vxi, 'INSTR') +class VXIInstrument(Resource): + """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`. + """ + + +@Resource.register(constants.InterfaceType.vxi, 'MEMACC') +class VXIMemory(RegisterBasedResource): + """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`. + """ diff --git a/pyvisa/rname.py b/pyvisa/rname.py new file mode 100644 index 0000000..f11f6db --- /dev/null +++ b/pyvisa/rname.py @@ -0,0 +1,575 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.rname + ~~~~~~~~~~~~ + + Functions and classes to parse and assemble resource name. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import re +import contextlib +from collections import namedtuple, defaultdict + +from . import constants, errors, logger + +# :type: set[str] +_INTERFACE_TYPES = set() + +# Resource Class for Interface type +# :type: dict[str, set[str]] +_RESOURCE_CLASSES = defaultdict(set) + +# :type: dict[(str, str), ResourceName] +_SUBCLASSES = {} + +# DEFAULT Resource Class for a given interface type. +# :type: dict[str, str] +_DEFAULT_RC = {} + + +class InvalidResourceName(ValueError): + """Exception raised when the resource name cannot be parsed. + """ + + def __init__(self, msg): + self.msg = msg + + @classmethod + def bad_syntax(cls, syntax, resource_name, ex=None): + """Exception used 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, + resource_name=None): + """Exception used when the subclass for a given interface type / resource class pair + cannot be found. + """ + + msg = "Parser for not found (%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, resource_name=None): + """Exception used 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): + return self.msg + + +def register_subclass(cls): + """Register a subclass for a given interface type and resource class. + """ + + 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(object): + """Base class for ResourceNames to be used as a Mixin + """ + + # Interface type string + interface_type = '' + + # Resource class string + resource_class = '' + + # Specifices if the resource class part of the string is optional. + is_rc_optional = False + + # Formatting string for canonical + _canonical_fmt = '' + + # VISA syntax for resource + _visa_syntax = '' + + # Resource name provided by the user (not empty only when parsing) + user = '' + + @property + def interface_type_const(self): + try: + return getattr(constants.InterfaceType, self.interface_type.lower()) + except: + return constants.InterfaceType.unknown + + @classmethod + def from_string(cls, resource_name): + """Parse a resource name and return a ResourceName + + :type resource_name: str + :rtype: ResourceName + + :raises InvalidResourceName: 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 + + 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 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): + interface_type = kwargs.pop('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: + return subclass(**kwargs) + except ValueError as ex: + raise InvalidResourceName(str(ex)) + + def __str__(self): + return self._canonical_fmt.format(self) + + +def build_rn_class(interface_type, resource_parts, resource_class, + is_rc_optional=True): + """Builds a resource name class by mixing a named tuple and ResourceName. + + It also registers the class. + + The field names are changed to lower case and the spaces replaced + by underscores ('_'). + + :param interface_type: the interface type + :type: interface_type: str + :param resource_parts: each of the parts of the resource name indicating + name and default value. + Use None for mandatory fields. + :type resource_parts: tuple[(str, str)] + :param resource_class: the resource class + :type resource_class: str + :param is_rc_optional: indicates if the resource class part is optional + :type is_rc_optional: boolean. + """ + + interface_type = interface_type.upper() + resource_class = resource_class.upper() + + syntax = interface_type + fmt = interface_type + fields = [] + + # Contains the resource parts but using python friendly names + # (all lower case and replacing spaces by underscores) + p_resource_parts = [] + + kwdoc = [] + + # Assemble the syntax and format string based on the resource parts + for ndx, (name, default_value) in enumerate(resource_parts): + pname = name.lower().replace(' ', '_') + fields.append(pname) + p_resource_parts.append((pname, default_value)) + + sep = '::' if ndx else '' + + fmt += sep + '{0.%s}' % pname + + if default_value is None: + syntax += sep + name + else: + syntax += '[' + sep + name + ']' + + kwdoc.append('- %s (%s)' % (pname, 'required' if default_value is None + else default_value)) + + fmt += '::' + resource_class + + if not is_rc_optional: + syntax += '::' + resource_class + else: + syntax += '[' + '::' + resource_class + ']' + + class _C(namedtuple('Internal', ' '.join(fields)), ResourceName): + """%s %s" + + Can be created with the following keyword only arguments: + %s + + Format : + %s + """ % (resource_class, interface_type, ' \n'.join(kwdoc), syntax) + + def __new__(cls, **kwargs): + new_kwargs = dict(p_resource_parts, **kwargs) + + for key, value in new_kwargs.items(): + if value is None: + raise ValueError(key + ' is a required parameter') + + return super(_C, cls).__new__(cls, **new_kwargs) + + @classmethod + def from_parts(cls, *parts): + + if len(parts) < sum(1 for _, v in p_resource_parts + if v is not None): + raise ValueError('not enough parts') + elif len(parts) > len(p_resource_parts): + raise ValueError('too many parts') + + (k, default), rp = p_resource_parts[0], p_resource_parts[1:] + + # The first part (just after the interface_type) is the only + # optional part which can be and empty and therefore the + # default value should be used. + p, pending = parts[0], parts[1:] + kwargs = {k: default if p == '' else p} + + # The rest of the parts are consumed when mandatory elements are required. + while len(pending) < len(rp): + (k, default), rp = rp[0], rp[1:] + if default is None: + if not parts: + raise ValueError(k + ' part is mandatory') + p, pending = pending[0], pending[1:] + if not p: + raise ValueError(k + ' part is mandatory') + kwargs[k] = p + else: + kwargs[k] = default + + # When the length of the pending provided and resource parts + # are equal, we just consume everything. + kwargs.update((k, p) for (k, v), p in zip(rp, pending)) + + return cls(**kwargs) + + _C.interface_type = interface_type + _C.resource_class = resource_class + _C.is_rc_optional = is_rc_optional + _C._canonical_fmt = fmt + _C._visa_syntax = syntax + + _C.__name__ = str(interface_type + resource_class.title()) + + return register_subclass(_C) + +# Build subclasses for each resource + +# Reference for the GPIB secondary address +# https://www.mathworks.com/help/instrument/secondaryaddress.html +GPIBInstr = build_rn_class('GPIB', + (('board', '0'), ('primary address', None), + ('secondary address', '0')), + 'INSTR') + +GPIBIntfc = build_rn_class('GPIB', (('board', '0'), ), 'INTFC', False) + +ASRLInstr = build_rn_class('ASRL', (('board', '0'), ), 'INSTR') + +TCPIPInstr = build_rn_class('TCPIP', (('board', '0'), ('host address', None), + ('LAN device name', 'inst0'), ), 'INSTR') + +TCPIPSocket = build_rn_class('TCPIP', (('board', '0'), ('host address', None), + ('port', None), ), 'SOCKET', False) + +USBInstr = build_rn_class('USB', + (('board', '0'), ('manufacturer ID', None), + ('model code', None), ('serial number', None), + ('USB interface number', '0')), 'INSTR') + +USBRaw = build_rn_class('USB', (('board', '0'), ('manufacturer ID', None), + ('model code', None), ('serial number', None), + ('USB interface number', '0')), 'RAW', False) + +PXIBackplane = build_rn_class('PXI', (('interface', '0'), + ('chassis number', None)), 'BACKPLANE', + False) + +PXIMemacc = build_rn_class('PXI', (('interface', '0'), ), 'MEMACC', False) + +VXIBackplane = build_rn_class('VXI', (('board', '0'), + ('VXI logical address', '0')), + 'BACKPLANE', False) + +VXIInstr = build_rn_class('VXI', (('board', '0'), + ('VXI logical address', None)), 'INSTR', + True) + +VXIMemacc = build_rn_class('VXI', (('board', '0'), ), 'MEMACC', False) + +VXIServant = build_rn_class('VXI', (('board', '0'), ), 'SERVANT', False) + +# TODO 3 types of PXI INSTR +# TODO ENET-Serial INSTR +# TODO Remote NI-VISA + + +def assemble_canonical_name(**kwargs): + """Given a set of keyword arguments defining a resource name, + return the canonical resource name. + """ + return str(ResourceName.from_kwargs(**kwargs)) + + +def to_canonical_name(resource_name): + """Parse a resource name and return the canonical version. + + :type resource_name: str + :rtype: str + """ + return str(ResourceName.from_string(resource_name)) + + +parse_resource_name = ResourceName.from_string + + +def filter(resources, query): + """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. + + + :param resources: iterable of resources. + :param query: query expression. + """ + + 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)) + + +def filter2(resources, query, open_resource): + """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. + + :param resources: iterable of resources. + :param query: query expression. + :param open_resource: function to open the resource. + """ + + 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 filtered + + optional = optional.replace('&&', 'and').replace('||', 'or').replace('!', 'not ') + optional = optional.replace('VI_', 'res.VI_') + + class AttrGetter(): + + def __init__(self, resource_name): + self.resource_name = resource_name + self.parsed = parse_resource_name(resource_name) + self.resource = None + + def __getattr__(self, item): + if item == 'VI_ATTR_INTF_NUM': + return int(self.parsed.board) + elif item == 'VI_ATTR_MANF_ID': + return self.parsed.manufacturer_id + elif item == 'VI_ATTR_MODEL_CODE': + return self.parsed.model_code + elif item == 'VI_ATTR_USB_SERIAL_NUM': + return self.parsed.serial_number + elif item == 'VI_ATTR_USB_INTFC_NUM': + return int(self.parsed.board) + elif item == 'VI_ATTR_TCPIP_ADDR': + return self.parsed.host_address + elif item == 'VI_ATTR_TCPIP_DEVICE_NAME': + return self.parsed.lan_device_name + elif item == 'VI_ATTR_TCPIP_PORT': + return int(self.parsed.port) + elif item == 'VI_ATTR_INTF_NUM': + return int(self.parsed.board) + elif item == 'VI_ATTR_GPIB_PRIMARY_ADDR': + return int(self.parsed.primary_address) + elif item == 'VI_ATTR_GPIB_SECONDARY_ADDR': + return int(self.parsed.secondary_address) + elif item == 'VI_ATTR_PXI_CHASSIS': + return self.parsed.chassis_number + elif item == 'VI_ATTR_MAINFRAME_LA': + return self.parsed.vxi_logical_address + + if self.resource is None: + self.resource = open_resource(self.resource_name) + + return self.resource.get_visa_attribute(item) + + @contextlib.contextmanager + def open_close(resource_name): + getter = AttrGetter(resource_name) + yield getter + if getter.resource is not None: + getter.resource.close() + + selected = [] + for rn in filtered: + with open_close(rn) as getter: + if eval(optional, None, dict(res=getter)): + selected.append(rn) + + + diff --git a/pyvisa/shell.py b/pyvisa/shell.py new file mode 100644 index 0000000..755b49b --- /dev/null +++ b/pyvisa/shell.py @@ -0,0 +1,428 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- +""" + pyvisa.shell + ~~~~~~~~~~~~ + + Shell for interactive testing. + + This file is taken from the Lantz Project. + + :copyright: (c) 2014 by PyVISA Authors, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +import cmd +import sys + +from .compat import input +from . import ResourceManager, attributes, constants, VisaIOError +from .thirdparty import prettytable + +if sys.platform == 'darwin': + + class Cmd(cmd.Cmd): + + # This has been patched to enable autocompletion on Mac OSX + def cmdloop(self, intro=None): + """Repeatedly issue a prompt, accept input, parse an initial prefix + off the received input, and dispatch to action methods, passing them + the remainder of the line as argument. + """ + + self.preloop() + if self.use_rawinput and self.completekey: + try: + import readline + self.old_completer = readline.get_completer() + readline.set_completer(self.complete) + + if 'libedit' in readline.__doc__: + # readline linked to BSD libedit + if self.completekey == 'tab': + key = '^I' + else: + key = self.completekey + readline.parse_and_bind('bind %s rl_complete' % (key,)) + else: + # readline linked to the real readline + readline.parse_and_bind(self.completekey + ': complete') + + except ImportError: + pass + try: + if intro is not None: + self.intro = intro + if self.intro: + self.stdout.write(str(self.intro) + "\n") + stop = None + while not stop: + if self.cmdqueue: + line = self.cmdqueue.pop(0) + else: + if self.use_rawinput: + try: + line = input(self.prompt) + except EOFError: + line = 'EOF' + else: + self.stdout.write(self.prompt) + self.stdout.flush() + line = self.stdin.readline() + if not len(line): + line = 'EOF' + else: + line = line.rstrip('\r\n') + line = self.precmd(line) + stop = self.onecmd(line) + stop = self.postcmd(stop, line) + self.postloop() + finally: + if self.use_rawinput and self.completekey: + try: + import readline + readline.set_completer(self.old_completer) + except ImportError: + pass +else: + Cmd = cmd.Cmd + + +class VisaShell(Cmd): + """Shell for interactive testing. + """ + + intro = '\nWelcome to the VISA shell. Type help or ? to list commands.\n' + prompt = '(visa) ' + + use_rawinput = True + + def __init__(self, library_path=''): + Cmd.__init__(self) + 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. + #: list[tuple(str, str)] + self.resources = [] + + #: Resource in use + #: pyvisa.resources.Resource + self.current = None + + #: list[str] + self.py_attr = [] + #: list[str] + self.vi_attr = [] + + 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): + 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): + 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): + """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') + elif len(args) == 1: + # Get + 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) + else: + 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 + try: + print(getattr(self.current, attr_name)) + print('Done') + except Exception as e: + print(e) + + def complete_attr(self, text, line, begidx, endidx): + 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) + else: + args = args.split(' ') + 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): + """. + """ + return True + + +def main(library_path=''): + VisaShell(library_path).cmdloop() + diff --git a/pyvisa/testsuite/__init__.py b/pyvisa/testsuite/__init__.py new file mode 100644 index 0000000..acd8991 --- /dev/null +++ b/pyvisa/testsuite/__init__.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- + +from __future__ import (division, unicode_literals, print_function, + absolute_import) + +import os +import logging +import warnings +import unittest +from contextlib import contextmanager + +from logging.handlers import BufferingHandler + +from pyvisa import logger +from pyvisa.compat import PYTHON3 + + +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(unittest.TestCase): + + CHECK_NO_WARNING = True + + @contextmanager + def capture_log(self, level=logging.DEBUG): + th = TestHandler() + th.setLevel(level) + logger.addHandler(th) + if self._test_handler is None: + yield th.buffer + else: + l = len(self._test_handler.buffer) + yield th.buffer + self._test_handler.buffer = self._test_handler.buffer[:l] + + def setUp(self): + self._test_handler = None + if self.CHECK_NO_WARNING: + self._test_handler = th = TestHandler() + th.setLevel(logging.WARNING) + logger.addHandler(th) + + def tearDown(self): + if self._test_handler is not None: + buf = self._test_handler.buffer + l = len(buf) + msg = '\n'.join(record.get('msg', str(record)) for record in buf) + self.assertEqual(l, 0, msg='%d warnings raised.\n%s' % (l, msg)) + + if not PYTHON3: + @contextmanager + def assertWarns(self, category): + """Backport for Python 2 + + """ + with warnings.catch_warnings(record=True) as w: + # Cause all warnings to always be triggered. + warnings.simplefilter("always") + # Trigger a warning. + yield + # Verify some things + assert len(w) == 1, 'No warning raised' + assert issubclass(w[-1].category, category) + + +def testsuite(): + """A testsuite that has all the pyvisa tests. + """ + return unittest.TestLoader().discover(os.path.dirname(__file__)) + + +def main(): + """Runs the testsuite as command line application. + """ + try: + unittest.main() + except Exception as e: + print('Error: %s' % e) + + +def run(): + """Run all tests. + + :return: a :class:`unittest.TestResult` object + """ + test_runner = unittest.TextTestRunner() + return test_runner.run(testsuite()) diff --git a/pyvisa/testsuite/test_errors.py b/pyvisa/testsuite/test_errors.py new file mode 100644 index 0000000..d5bb61b --- /dev/null +++ b/pyvisa/testsuite/test_errors.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- + +from __future__ import division, unicode_literals, print_function, absolute_import + +import pickle + +from pyvisa.testsuite import BaseTestCase + +from pyvisa import errors + + +class TestPicleUnpickle(BaseTestCase): + def _test_pickle_unpickle(self, instance): + pickled = pickle.dumps(instance) + unpickled = pickle.loads(pickled) + self.assertIsInstance(unpickled, type(instance)) + for attr in instance.__dict__: + self.assertEqual(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()) + + def InvalidSession(self): + self._test_pickle_unpickle(errors.InvalidSession()) diff --git a/pyvisa/testsuite/test_rname.py b/pyvisa/testsuite/test_rname.py new file mode 100644 index 0000000..8e77d9c --- /dev/null +++ b/pyvisa/testsuite/test_rname.py @@ -0,0 +1,257 @@ +# -*- coding: utf-8 -*- + +from __future__ import (division, unicode_literals, print_function, + absolute_import) + +import unittest +from pyvisa.testsuite import BaseTestCase + +from pyvisa import rname + +parse = rname.ResourceName.from_string + + +class TestParsers(BaseTestCase): + + def _parse_test(self, rn, **kwargs): + p = parse(rn) + r = dict((k, getattr(p, k)) for k in p._fields + ('interface_type', 'resource_class')) + r['canonical_resource_name'] = str(p) + self.assertEqual(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): + + run_list = ( + 'GPIB0::8::65535::INSTR', + 'TCPIP0::localhost:1111::inst0::INSTR', + 'ASRL1::INSTR', + 'USB0::0x1111::0x2222::0x4445::0::RAW', + 'USB0::0x1111::0x2222::0x1234::0::INSTR', + 'TCPIP0::localhost::10001::SOCKET', + 'GPIB9::8::65535::INSTR', + 'ASRL11::INSTR', + 'ASRL2::INSTR' + ) + + def _test_filter(self, expr, *correct): + ok = tuple(self.run_list[n] for n in correct) + self.assertEqual(rname.filter(self.run_list, expr), ok) + + def test_filter(self): + self._test_filter('?*::INSTR', 0, 1, 2, 4, 6, 7, 8) + self._test_filter('GPIB?+INSTR', 0, 6) + self._test_filter('GPIB[0-8]*::?*INSTR', 0) + self._test_filter('GPIB[^0]::?*INSTR', 6) + self._test_filter('ASRL1+::INSTR', 2, 7) + self._test_filter('(GPIB|VXI)?*INSTR', 0, 6) + self._test_filter('?*', *tuple(range(len(self.run_list)))) diff --git a/pyvisa/testsuite/test_util.py b/pyvisa/testsuite/test_util.py new file mode 100644 index 0000000..00501eb --- /dev/null +++ b/pyvisa/testsuite/test_util.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- + +from __future__ import (division, unicode_literals, print_function, + absolute_import) + +from pyvisa.testsuite import BaseTestCase + +from pyvisa import util + +try: + # noinspection PyPackageRequirements + import numpy as np +except ImportError: + np = None + + +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] + with self.assertWarns(FutureWarning): + p = util.parse_binary(s, is_big_endian=False, is_single=True) + for a, b in zip(p, e): + self.assertAlmostEqual(a, b) + + # Test handling indefinite length block + p = util.from_ieee_block(s, datatype='f', is_big_endian=False) + for a, b in zip(p, e): + self.assertAlmostEqual(a, 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): + self.assertAlmostEqual(a, b) + + p = util.from_hp_block(b'#A\x0e\x00' + s[2:], datatype='f', + is_big_endian=False) + for a, b in zip(p, e): + self.assertAlmostEqual(a, 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_converstion(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_converstion(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_converstion(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_converstion(values, tblock, fblock, + msg) + + def round_trip_block_converstion(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: + self.assertEqual(conv, parsed, msg) diff --git a/pyvisa/thirdparty/__init__.py b/pyvisa/thirdparty/__init__.py new file mode 100644 index 0000000..6a0eea1 --- /dev/null +++ b/pyvisa/thirdparty/__init__.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.thirdparty + ~~~~~~~~~~~~~~~~~ + + Third party libraries and modules bundled with PyVISA. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" diff --git a/pyvisa/thirdparty/prettytable.py b/pyvisa/thirdparty/prettytable.py new file mode 100644 index 0000000..8abb952 --- /dev/null +++ b/pyvisa/thirdparty/prettytable.py @@ -0,0 +1,1475 @@ +#!/usr/bin/env python +# +# Copyright (c) 2009-2013, Luke Maurits +# All rights reserved. +# With contributions from: +# * Chris Clark +# * Klein Stephane +# +# 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. + +__version__ = "0.7.2" + +import copy +import csv +import random +import re +import sys +import textwrap +import itertools +import unicodedata + +py3k = sys.version_info[0] >= 3 +if py3k: + unicode = str + basestring = str + itermap = map + iterzip = zip + uni_chr = chr + from html.parser import HTMLParser +else: + itermap = itertools.imap + iterzip = itertools.izip + uni_chr = unichr + from HTMLParser import HTMLParser + +if py3k and sys.version_info[1] >= 2: + from html import escape +else: + from cgi import escape + +# hrule styles +FRAME = 0 +ALL = 1 +NONE = 2 +HEADER = 3 + +# Table styles +DEFAULT = 10 +MSWORD_FRIENDLY = 11 +PLAIN_COLUMNS = 12 +RANDOM = 20 + +_re = re.compile("\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 + 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 + 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""" + + self.encoding = kwargs.get("encoding", "UTF-8") + + # Data + self._field_names = [] + self._align = {} + self._valign = {} + self._max_width = {} + self._rows = [] + if field_names: + self.field_names = field_names + else: + self._widths = [] + + # Options + self._options = "start end fields header border sortby reversesort sort_key attributes format hrules vrules".split() + self._options.extend("int_format float_format padding_width left_padding_width right_padding_width".split()) + self._options.extend("vertical_char horizontal_char junction_char header_style valign xhtml print_empty".split()) + for option in self._options: + if option in kwargs: + self._validate_option(option, kwargs[option]) + else: + kwargs[option] = 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) + + self._int_format = kwargs["int_format"] or {} + self._float_format = kwargs["float_format"] or {} + 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 + 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 MANAGMENT 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", "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"): + 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) + else: + raise Exception("Unrecognised option: %s!" % option) + + 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 %s: %s!" % (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() + 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 # + ############################## + + def _get_field_names(self): + return self._field_names + """The names of the fields + + Arguments: + + fields - list or tuple of field names""" + def _set_field_names(self, val): + val = [self._unicode(x) for x in val] + self._validate_option("field_names", val) + 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: + for field in self._field_names: + self._align[field] = "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: + for field in self._field_names: + self._valign[field] = "t" + field_names = property(_get_field_names, _set_field_names) + + def _get_align(self): + return self._align + def _set_align(self, val): + self._validate_align(val) + for field in self._field_names: + self._align[field] = val + align = property(_get_align, _set_align) + + def _get_valign(self): + return self._valign + def _set_valign(self, val): + self._validate_valign(val) + for field in self._field_names: + self._valign[field] = val + valign = property(_get_valign, _set_valign) + + def _get_max_width(self): + return self._max_width + def _set_max_width(self, val): + self._validate_option("max_width", val) + for field in self._field_names: + self._max_width[field] = val + max_width = property(_get_max_width, _set_max_width) + + def _get_fields(self): + """List or tuple of field names to include in displays + + Arguments: + + fields - list or tuple of field names to include in displays""" + return self._fields + def _set_fields(self, val): + self._validate_option("fields", val) + self._fields = val + fields = property(_get_fields, _set_fields) + + def _get_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 + + def _set_start(self, val): + self._validate_option("start", val) + self._start = val + start = property(_get_start, _set_start) + + def _get_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 + def _set_end(self, val): + self._validate_option("end", val) + self._end = val + end = property(_get_end, _set_end) + + def _get_sortby(self): + """Name of field by which to sort rows + + Arguments: + + sortby - field name to sort by""" + return self._sortby + def _set_sortby(self, val): + self._validate_option("sortby", val) + self._sortby = val + sortby = property(_get_sortby, _set_sortby) + + def _get_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 + def _set_reversesort(self, val): + self._validate_option("reversesort", val) + self._reversesort = val + reversesort = property(_get_reversesort, _set_reversesort) + + def _get_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 + def _set_sort_key(self, val): + self._validate_option("sort_key", val) + self._sort_key = val + sort_key = property(_get_sort_key, _set_sort_key) + + def _get_header(self): + """Controls printing of table header with field names + + Arguments: + + header - print a header showing field names (True or False)""" + return self._header + def _set_header(self, val): + self._validate_option("header", val) + self._header = val + header = property(_get_header, _set_header) + + def _get_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 + def _set_header_style(self, val): + self._validate_header_style(val) + self._header_style = val + header_style = property(_get_header_style, _set_header_style) + + def _get_border(self): + """Controls printing of border around table + + Arguments: + + border - print a border around the table (True or False)""" + return self._border + def _set_border(self, val): + self._validate_option("border", val) + self._border = val + border = property(_get_border, _set_border) + + def _get_hrules(self): + """Controls printing of horizontal rules after rows + + Arguments: + + hrules - horizontal rules style. Allowed values: FRAME, ALL, HEADER, NONE""" + return self._hrules + def _set_hrules(self, val): + self._validate_option("hrules", val) + self._hrules = val + hrules = property(_get_hrules, _set_hrules) + + def _get_vrules(self): + """Controls printing of vertical rules between columns + + Arguments: + + vrules - vertical rules style. Allowed values: FRAME, ALL, NONE""" + return self._vrules + def _set_vrules(self, val): + self._validate_option("vrules", val) + self._vrules = val + vrules = property(_get_vrules, _set_vrules) + + def _get_int_format(self): + """Controls formatting of integer data + Arguments: + + int_format - integer format string""" + return self._int_format + def _set_int_format(self, val): +# self._validate_option("int_format", val) + for field in self._field_names: + self._int_format[field] = val + int_format = property(_get_int_format, _set_int_format) + + def _get_float_format(self): + """Controls formatting of floating point data + Arguments: + + float_format - floating point format string""" + return self._float_format + def _set_float_format(self, val): +# self._validate_option("float_format", val) + for field in self._field_names: + self._float_format[field] = val + float_format = property(_get_float_format, _set_float_format) + + def _get_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 + def _set_padding_width(self, val): + self._validate_option("padding_width", val) + self._padding_width = val + padding_width = property(_get_padding_width, _set_padding_width) + + def _get_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 + def _set_left_padding_width(self, val): + self._validate_option("left_padding_width", val) + self._left_padding_width = val + left_padding_width = property(_get_left_padding_width, _set_left_padding_width) + + def _get_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 + def _set_right_padding_width(self, val): + self._validate_option("right_padding_width", val) + self._right_padding_width = val + right_padding_width = property(_get_right_padding_width, _set_right_padding_width) + + def _get_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 + def _set_vertical_char(self, val): + val = self._unicode(val) + self._validate_option("vertical_char", val) + self._vertical_char = val + vertical_char = property(_get_vertical_char, _set_vertical_char) + + def _get_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 + def _set_horizontal_char(self, val): + val = self._unicode(val) + self._validate_option("horizontal_char", val) + self._horizontal_char = val + horizontal_char = property(_get_horizontal_char, _set_horizontal_char) + + def _get_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 + def _set_junction_char(self, val): + val = self._unicode(val) + self._validate_option("vertical_char", val) + self._junction_char = val + junction_char = property(_get_junction_char, _set_junction_char) + + def _get_format(self): + """Controls whether or not HTML tables are formatted to match styling options + + Arguments: + + format - True or False""" + return self._format + def _set_format(self, val): + self._validate_option("format", val) + self._format = val + format = property(_get_format, _set_format) + + def _get_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 + def _set_print_empty(self, val): + self._validate_option("print_empty", val) + self._print_empty = val + print_empty = property(_get_print_empty, _set_print_empty) + + def _get_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 + def _set_attributes(self, val): + self._validate_option("attributes", val) + self._attributes = val + attributes = property(_get_attributes, _set_attributes) + + ############################## + # 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 == RANDOM: + self._set_random_style() + else: + raise Exception("Invalid pre-set style!") + + 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("~!@#$%^&*()_+|-=\{}[];':\",./;<>?") + self.horizontal_char = random.choice("~!@#$%^&*()_+|-=\{}[];':\",./;<>?") + self.junction_char = random.choice("~!@#$%^&*()_+|-=\{}[];':\",./;<>?") + + ############################## + # 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_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]) + 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.""" + + # Make a copy of only those rows in the slice range + rows = copy.deepcopy(self._rows[options["start"]:options["end"]]) + # Sort if necessary + 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] + 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: + + 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) + + # Add header or top of border + self._hrule = self._stringify_hrule(options) + 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_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) + + ############################## + # HTML STRING METHODS # + ############################## + + def get_html_string(self, **kwargs): + + """Return string representation of HTML formatted version of table in current state. + + Arguments: + + 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 = [] + open_tag.append("") + lines.append("".join(open_tag)) + + # 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
") + + 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 = [] + open_tag.append("") + lines.append("".join(open_tag)) + + # 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" % (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" % (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, 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): + + 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 + +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 + + def handle_starttag(self,tag, attrs): + self.active = tag + if tag == "th": + self.is_last_row_header = True + + def handle_endtag(self,tag): + if tag in ["th", "td"]: + stripped_content = self.last_content.strip() + self.last_row.append(stripped_content) + 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] == True: + 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(): + + x = PrettyTable(["City name", "Area", "Population", "Annual Rainfall"]) + x.sortby = "Population" + x.reversesort = True + x.int_format["Area"] = "04d" + x.float_format = "6.1f" + 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) + +if __name__ == "__main__": + main() diff --git a/pyvisa/util.py b/pyvisa/util.py new file mode 100644 index 0000000..7b01435 --- /dev/null +++ b/pyvisa/util.py @@ -0,0 +1,739 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.util + ~~~~~~~~~~~ + + General utility functions. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see LICENSE for more details. +""" + +from __future__ import (division, unicode_literals, print_function, + absolute_import) + +import functools +import io +import os +import platform +import sys +import subprocess +import warnings +import inspect +from subprocess import check_output + +from .compat import (string_types, OrderedDict, struct, + int_to_bytes, int_from_bytes, PYTHON3) +from . import __version__, logger + + +try: + import numpy as np +except ImportError: + np = None + + +def _use_numpy_routines(container): + """Should optimized numpy routines be used to extract the 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))): + return True + + return False + + +def read_user_library_path(): + """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 + + Return `None` if configuration files or keys are not present. + + """ + try: + from ConfigParser import (SafeConfigParser as ConfigParser, + NoSectionError) + except ImportError: + from configparser import ConfigParser, 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 (KeyError, NoSectionError): + logger.debug('KeyError or NoSectionError while reading config file') + return None + + +class LibraryPath(str): + + #: Architectural information (32, ) or (64, ) or (32, 64) + _arch = None + + def __new__(cls, path, found_by='auto'): + obj = super(LibraryPath, cls).__new__(cls, path) + obj.path = path + obj.found_by = found_by + + return obj + + @property + def arch(self): + if self._arch is None: + try: + self._arch = get_arch(self.path) + except: + self._arch = tuple() + + return self._arch + + @property + def is_32bit(self): + if not self.arch: + return 'n/a' + return 32 in self.arch + + @property + def is_64bit(self): + if not self.arch: + return 'n/a' + return 64 in self.arch + + @property + def bitness(self): + if not self.arch: + return 'n/a' + return ', '.join(str(a) for a in self.arch) + + +def warn_for_invalid_kwargs(keyw, allowed_keys): + 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): + 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): + 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 = { + 's': str, + 'b': functools.partial(int, base=2), + 'c': chr, + 'd': int, + 'o': functools.partial(int, base=8), + 'x': functools.partial(int, base=16), + 'X': functools.partial(int, base=16), + 'e': float, + 'E': float, + 'f': float, + 'F': float, + 'g': float, + 'G': float, +} + +_np_converters = { + 'd': 'i', + 'e': 'f', + 'E': 'f', + 'f': 'f', + 'F': 'f', + 'g': 'f', + 'G': 'f', +} + + +def from_ascii_block(ascii_data, converter='f', separator=',', container=list): + """Parse ascii data and return an iterable of numbers. + + :param ascii_data: data to be parsed. + :type ascii_data: str + :param converter: function used to convert each value. + Defaults to float + :type converter: callable + :param separator: a callable that split the str into individual elements. + If a str is given, data.split(separator) is used. + :type: separator: (str) -> collections.Iterable[T] | str + :param container: container type to use for the output data. + """ + if (_use_numpy_routines(container) and + isinstance(converter, string_types) and + isinstance(separator, string_types) and + converter in _np_converters): + return np.fromstring(ascii_data, _np_converters[converter], + sep=separator) + + if isinstance(converter, string_types): + try: + converter = _converters[converter] + except KeyError: + raise ValueError('Invalid code for converter: %s not in %s' % + (converter, str(tuple(_converters.keys())))) + + if isinstance(separator, string_types): + 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, converter='f', separator=','): + """Turn an iterable of numbers in an ascii block of data. + + :param iterable: data to be parsed. + :type iterable: collections.Iterable[T] + :param converter: function used to convert each value. + String formatting codes are also accepted. + Defaults to str. + :type converter: callable | str + :param separator: a callable that split the str into individual elements. + If a str is given, data.split(separator) is used. + :type: separator: (collections.Iterable[T]) -> str | str + + :rtype: str + """ + + if isinstance(separator, string_types): + separator = separator.join + + if isinstance(converter, string_types): + converter = '%' + converter + block = separator(converter % val for val in iterable) + else: + block = separator(converter(val) for val in iterable) + return block + + +def parse_binary(bytes_data, is_big_endian=False, is_single=False): + """Parse ascii data and return an iterable of numbers. + + To be deprecated in 1.7 + + :param bytes_data: data to be parsed. + :param is_big_endian: boolean indicating the endianness. + :param is_single: boolean indicating the type (if not is double) + :return: + """ + warnings.warn('parse_binary is deprecated and will be removed in ' + '1.10, use read_ascii_values or read_binary_values ' + 'instead.', FutureWarning) + data = bytes_data + + hash_sign_position = bytes_data.find(b"#") + if hash_sign_position == -1: + raise ValueError('Could not find valid hash position') + + if hash_sign_position > 0: + data = data[hash_sign_position:] + + data_1 = data[1:2].decode('ascii') + + if data_1.isdigit() and int(data_1) > 0: + number_of_digits = int(data_1) + # I store data and data_length in two separate variables in case + # that data is too short. FixMe: Maybe I should raise an error if + # it's too long and the trailing part is not just CR/LF. + data_length = int(data[2:2 + number_of_digits]) + data = data[2 + number_of_digits:2 + number_of_digits + data_length] + else: + data = data[2:] + if data[-1:].decode('ascii') == "\n": + data = data[:-1] + data_length = len(data) + + if is_big_endian: + endianess = ">" + else: + endianess = "<" + + try: + if is_single: + fmt = endianess + str(data_length // 4) + 'f' + else: + fmt = endianess + str(data_length // 8) + 'd' + + result = list(struct.unpack(fmt, data)) + except struct.error: + raise ValueError("Binary data itself was malformed") + + return result + + +def parse_ieee_block_header(block): + """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 + + :param block: IEEE block. + :type block: bytes | bytearray + :return: (offset, data_length) + :rtype: (int, int) + """ + begin = block.find(b'#') + if begin < 0: + raise ValueError("Could not find hash sign (#) indicating the start of" + " the block.") + + 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 = len(block) - offset - 1 + + return offset, data_length + + +def parse_hp_block_header(block, is_big_endian): + """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. + + :param block: HP block. + :type block: bytes | bytearray + :param is_big_endian: boolean indicating endianess. + :return: (offset, data_length) + :rtype: (int, int) + + """ + begin = block.find(b'#A') + if begin < 0: + raise ValueError("Could not find the standard block header (#A) " + "indicating the start of the block.") + 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, datatype='f', is_big_endian=False, container=list): + """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 + + :param block: HP block. + :type block: bytes | bytearray + :param datatype: the format string for a single element. See struct module. + :param is_big_endian: boolean indicating endianess. + :param container: container type to use for the output data. + :return: items + :rtype: type(container) + """ + offset, data_length = parse_ieee_block_header(block) + + 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, datatype='f', is_big_endian=False, container=list): + """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. + + :param block: IEEE block. + :type block: bytes | bytearray + :param datatype: the format string for a single element. See struct module. + :param is_big_endian: boolean indicating endianess. + :param container: container type to use for the output data. + :return: items + :rtype: type(container) + """ + offset, data_length = parse_hp_block_header(block, is_big_endian) + + 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, offset=0, data_length=None, datatype='f', + is_big_endian=False, container=list): + """Convert a binary block into an iterable of numbers. + + :param block: binary block. + :type block: bytes | bytearray + :param offset: offset at which the data block starts (default=0) + :param data_length: size in bytes of the data block + (default=len(block) - offset) + :param datatype: the format string for a single element. See struct module. + :param is_big_endian: boolean indicating endianess. + :param container: container type to use for the output data. + :return: items + :rtype: type(container) + """ + 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: + return container(struct.unpack_from(fullfmt, block, offset)) + except struct.error: + raise ValueError("Binary data was malformed") + + +def to_binary_block(iterable, header, datatype, is_big_endian): + """Convert an iterable of numbers into a block of data with a given header. + + :param iterable: an iterable of numbers. + :param header: the header which should prefix the binary block + :param datatype: the format string for a single element. See struct module. + :param is_big_endian: boolean indicating endianess. + :return: IEEE block. + :rtype: bytes + """ + array_length = len(iterable) + + endianess = '>' if is_big_endian else '<' + fullfmt = '%s%d%s' % (endianess, array_length, datatype) + + if isinstance(header, string_types): + header = bytes(header, 'ascii') if PYTHON3 else str(header) + + return header + struct.pack(fullfmt, *iterable) + + +def to_ieee_block(iterable, datatype='f', is_big_endian=False): + """Convert an iterable of numbers into a block of data in the IEEE format. + + :param iterable: an iterable of numbers. + :param datatype: the format string for a single element. See struct module. + :param is_big_endian: boolean indicating endianess. + :return: IEEE block. + :rtype: bytes + """ + 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, datatype='f', is_big_endian=False): + """Convert an iterable of numbers into a block of data in the HP format. + + :param iterable: an iterable of numbers. + :param datatype: the format string for a single element. See struct module. + :param is_big_endian: boolean indicating endianess. + :return: IEEE block. + :rtype: bytes + """ + + 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=True): + """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() + + 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, indent=''): + """Return a str with the system details. + """ + + l = ['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, string_types): + 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 + + l.extend(_to_list('Backends', d['backends'])) + + joiner = '\n' + indent + return indent + joiner.join(l) + '\n' + + +def get_debug_info(to_screen=True): + out = system_details_to_str(get_system_details()) + if not to_screen: + return out + print(out) + + +def pip_install(package): + try: + # noinspection PyPackageRequirements,PyUnresolvedReferences + import pip + 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): + with io.open(filename, 'rb') as fp: + dos_headers = fp.read(64) + _ = fp.read(4) + + magic, skip, offset = struct.unpack(str('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): + 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('') + + out = check_output(["file", filename], stderr=subprocess.STDOUT) + out = out.decode('ascii') + ret = [] + if this_platform.startswith('linux'): + if '32-bit' in out: + ret.append(32) + if '64-bit' in out: + ret.append(64) + elif this_platform == 'darwin': + if '(for architecture i386)' in out: + ret.append(32) + if '(for architecture x86_64)' in out: + ret.append(64) + + return tuple(ret) diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..9717861 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,4 @@ +[check-manifest] +ignore = + .travis.yml + tox.ini diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..2086c01 --- /dev/null +++ b/setup.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import sys + +try: + from setuptools import setup +except ImportError: + print('Please install or upgrade setuptools or pip to continue') + sys.exit(1) + + +def read(filename): + with open(filename, 'rb') as f: + return f.read().decode('utf8') + + +long_description = '\n\n'.join([read('README'), + read('AUTHORS'), + read('CHANGES')]) + +__doc__ = long_description + +requirements = [] +if sys.version_info < (3,): + requirements.append('enum34') + +setup(name='PyVISA', + description='Python VISA bindings for GPIB, RS232, TCPIP and USB instruments', + version='1.9.1', + long_description=long_description, + author='Torsten Bronger, Gregor Thalhammer', + author_email='bronger@physik.rwth-aachen.de', + maintainer='Hernan E. Grecco', + maintainer_email='hernan.grecco@gmail.com', + url='https://github.com/pyvisa/pyvisa', + test_suite='pyvisa.testsuite.testsuite', + keywords='VISA GPIB USB serial RS232 measurement acquisition', + license='MIT License', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', + install_requires=requirements, + 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 :: 2', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + ], + packages=['pyvisa', 'pyvisa.compat', + 'pyvisa.ctwrapper', + 'pyvisa.resources', + 'pyvisa.thirdparty', + 'pyvisa.testsuite'], + platforms="Linux, Windows,Mac", + entry_points={'console_scripts': + ['pyvisa-shell=visa:visa_shell', + 'pyvisa-info=visa:visa_info']}, + py_modules=['visa'], + use_2to3=False, + zip_safe=False) diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..c89b91e --- /dev/null +++ b/tox.ini @@ -0,0 +1,11 @@ +[tox] +envlist = py27,py34,py35,py36 + +[testenv] +deps= + pytest + sphinx + mock + +commands= + py.test diff --git a/visa.py b/visa.py new file mode 100644 index 0000000..6e1a164 --- /dev/null +++ b/visa.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +""" + pyvisa.visa + ~~~~~~~~~~~ + + Module to provide an import shortcut for the most common VISA operations. + + This file is part of PyVISA. + + :copyright: 2014 by PyVISA Authors, see AUTHORS for more details. + :license: MIT, see COPYING for more details. +""" + +from __future__ import division, unicode_literals, print_function, absolute_import + +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 + +def visa_main(command=None): + 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: ni)') + + if not command: + subparsers = parser.add_subparsers(title='command', dest='command') + + info_parser = subparsers.add_parser('info', help='print information to diagnose PyVISA') + + console_parser = 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 '') + +def visa_shell(): + visa_main('shell') + +def visa_info(): + visa_main('info') + +if __name__ == '__main__': + visa_main() -- cgit v1.2.3 From ed9a7e2db9412ca72491104d4b8bbd6534bca387 Mon Sep 17 00:00:00 2001 From: Sandro Tosi Date: Mon, 9 Sep 2019 05:51:59 +0200 Subject: Import pyvisa_1.9.1-2.debian.tar.xz [dgit import tarball pyvisa 1.9.1-2 pyvisa_1.9.1-2.debian.tar.xz] --- changelog | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++ control | 25 +++++++++ copyright | 148 +++++++++++++++++++++++++++++++++++++++++++++++++ gbp.conf | 2 + python3-pyvisa.docs | 1 + rules | 25 +++++++++ source/format | 1 + upstream/metadata | 6 ++ watch | 2 + 9 files changed, 365 insertions(+) create mode 100644 changelog create mode 100644 control create mode 100644 copyright create mode 100644 gbp.conf create mode 100644 python3-pyvisa.docs create mode 100755 rules create mode 100644 source/format create mode 100644 upstream/metadata create mode 100644 watch diff --git a/changelog b/changelog new file mode 100644 index 0000000..e6cfebf --- /dev/null +++ b/changelog @@ -0,0 +1,155 @@ +pyvisa (1.9.1-2) unstable; urgency=medium + + [ Ondřej Nový ] + * Use debhelper-compat instead of debian/compat. + + [ Sandro Tosi ] + * Team upload. + * Remove Python 2 support; Closes: #938296 + * debian/control + - bump Standards-Version to 4.4.0 (no changes needed) + + -- Sandro Tosi Sun, 08 Sep 2019 23:51:59 -0400 + +pyvisa (1.9.1-1) unstable; urgency=medium + + * New upstream release + - Drop patch + * debian/upstream/metadata added pointing to github + + -- Ruben Undheim Sun, 19 Aug 2018 22:22:03 +0200 + +pyvisa (1.9.0-1) unstable; urgency=medium + + * New upstream release + + [ Ondřej Nový ] + * debian/control: Set Vcs-* to salsa.debian.org + * debian/copyright: Use https protocol in Format field + * debian/control: Deprecating priority extra as per policy 4.0.1 + * debian/changelog: Remove trailing whitespaces + * debian/control: Remove ancient X-Python3-Version field + + [ Ruben Undheim ] + * Updated homepage URL, watch URL and source url in debian/copyright + * debian/copyright: Updates according to changes in new release + * debian/compat: compat level set to 11 + * debian/control: + - debhelper >= 11 + - Standards version 4.2.0 + * Deleted debian/.git-dpm + * debian/patches/0001-fix-build.patch: + - Fix an issue popping up when building on latest sid + + -- Ruben Undheim Sun, 05 Aug 2018 21:12:47 +0200 + +pyvisa (1.8-4) unstable; urgency=low + + * Moved python-pyvisa-py back from Depends to Recommends. (Closes: #836963) + This fixes a circular dependency issue. + + -- Ruben Undheim Thu, 22 Sep 2016 19:22:55 +0200 + +pyvisa (1.8-3) unstable; urgency=medium + + [ Ondřej Nový ] + * Fixed VCS URL (https) + + [ Ruben Undheim ] + * debian/control: + - Move libvisa0 from Depends to Suggests + - Move python-pyvisa-py from Recommends to Depends + - New Standards version 3.9.8 + + -- Ruben Undheim Sat, 27 Aug 2016 10:41:27 +0200 + +pyvisa (1.8-2) unstable; urgency=low + + * debian/control: + - Recommend pyvisa-py + - Small improvement of package description + + -- Ruben Undheim Sat, 12 Sep 2015 01:38:44 +0200 + +pyvisa (1.8-1) unstable; urgency=low + + * New upstream release + + -- Ruben Undheim Tue, 01 Sep 2015 22:26:12 +0200 + +pyvisa (1.7-1) unstable; urgency=medium + + * New upstream release + * Updated d/copyright with info about new files. + * d/control: + - transitional package pyvisa moved to Section "oldlibs" and description + changed. + + -- Ruben Undheim Fri, 29 May 2015 16:50:18 +0200 + +pyvisa (1.6.3-4) unstable; urgency=medium + + * d/control: + - Added missing install dependencies: python-pkg-resources and + python3-pkg-resources + + -- Ruben Undheim Thu, 28 May 2015 22:45:17 +0200 + +pyvisa (1.6.3-3) unstable; urgency=low + + * Uploaded to unstable + + -- Ruben Undheim Sat, 23 May 2015 11:55:57 +0200 + +pyvisa (1.6.3-2) experimental; urgency=low + + * Added python3 binary: python3-pyvisa + * Renamed pyvisa binary to python-pyvisa + * debian/copyright: + - Added copyright year and comment for Hernan E. Grecco + * debian/control: + - Added everything needed for building python3 binary as well + as python2 binary. + - Cleaned up Build-Depends list + - Section: python, Priority: optional + - python-pyvisa "replaces" and "breaks" pyvisa to provide backwards + compatibility + - pyvisa transitional dummy package added + * debian/docs --> python-pyvisa.docs and python3-pyvisa.docs + * debian/install --> python-pyvisa.install and python3-pyvisa.install + * debian/rules: + - Added --with python3 and --buildsystem=python_distutils + - More in override_dh_auto_clean to properly clean up + - override_dh_auto_build and override_dh_auto_install for building + python3 binary correctly. + + -- Ruben Undheim Mon, 16 Mar 2015 19:11:37 +0100 + +pyvisa (1.6.3-1) experimental; urgency=low + + * New upstream release (Closes: 775767) + - All patches removed + * New maintainer + * debian/control: + - Added new dependencies: dh-python, {python:Depends} + - Removed unneeded dependencies + - Standards-version to 3.9.6 + - Added X-Python-Version + * debian/copyright: + - Added new copyright holders + - Changed source URL + * debian/rules: + - Added override_dh_auto_clean to properly clean + - Install CHANGES as upstream changelog since it + is the newest + * debian/watch: Changed URL (upstream has changed) + * Added debian/gbp.conf to enable pristine-tar build + * Added debian/docs and debian/install for installing docs + + -- Ruben Undheim Thu, 12 Mar 2015 07:44:18 +0100 + +pyvisa (1.4-1) unstable; urgency=low + + * Initial release + + -- Simon Richter Tue, 29 Jan 2013 23:50:45 +0100 diff --git a/control b/control new file mode 100644 index 0000000..a8b5d41 --- /dev/null +++ b/control @@ -0,0 +1,25 @@ +Source: pyvisa +Section: python +Priority: optional +Maintainer: Debian Python Modules Team +Uploaders: Ruben Undheim +Build-Depends: debhelper-compat (= 11), + dh-python, + python3-all, + python3-setuptools +Standards-Version: 4.4.0 +X-Python-Version: all +Vcs-Browser: https://salsa.debian.org/python-team/modules/pyvisa +Vcs-Git: https://salsa.debian.org/python-team/modules/pyvisa.git +Homepage: https://pyvisa.readthedocs.io/ + +Package: python3-pyvisa +Architecture: all +Depends: python3-pkg-resources, ${python3:Depends}, ${misc:Depends} +Recommends: python3-pyvisa-py +Suggests: libvisa0 +Description: Python 3 bindings for Virtual Instrument Software Architecture + The VISA standard provides a common interface for communication with test + and measurement equipment. + . + This package provides Python 3 bindings for VISA. diff --git a/copyright b/copyright new file mode 100644 index 0000000..593bb84 --- /dev/null +++ b/copyright @@ -0,0 +1,148 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: pyvisa +Source: https://github.com/pyvisa/pyvisa + +Files: * +Copyright: 2005-2018 PyVISA Authors and contributors + 2005, 2006, 2007, 2008 Torsten Bronger + 2005, 2006, 2007, 2008 Gregor Thalhammer + 2012, 2013 Florian Bauer + 2013-2015 Hernan E. Grecco +License: MIT +Comment: Hernan E. Grecco is the current upstream and his commits (and copyright + dates) can be checked at https://github.com/hgrecco/pyvisa + +Files: docs/default.css +Copyright: ? David Goodger +License: public-domain + This stylesheet has been placed in the public domain. + +Files: pyvisa/thirdparty/prettytable.py +Copyright: 2009-2013 Luke Maurits +License: BSD-3-clause + +Files: pyvisa/compat/nullhandler.py + pyvisa/compat/struct.py +Copyright: 2013, 2015 PSF +License: PSF + +Files: pyvisa/compat/ordereddict.py +Copyright: 2009 Raymond Hettinger +License: MIT + +Files: docs/_themes/* +Copyright: 2010 Armin Ronacher +License: BSD-3-clause + +Files: docs/_themes/sphinx_rtd_theme/search.html + docs/_themes/sphinx_rtd_theme/layout_old.html +Copyright: 2007-2013 Sphinx team +License: BSD-3-clause + +Files: debian/* +Copyright: 2013 Simon Richter + 2015-2016,2018 Ruben Undheim +License: GPL-2+ + + + +License: MIT + 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. + + +License: GPL-2+ + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + . + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program. If not, see + . + On Debian systems, the complete text of the GNU General + Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". + + +License: BSD-3-clause + 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. + +License: PSF + 1. This LICENSE AGREEMENT is between the Python Software Foundation + ("PSF"), and the Individual or Organization ("Licensee") accessing and + otherwise using this software ("Python") in source or binary form and + its associated documentation. + . + 2. Subject to the terms and conditions of this License Agreement, PSF + hereby grants Licensee a nonexclusive, royalty-free, world-wide + license to reproduce, analyze, test, perform and/or display publicly, + prepare derivative works, distribute, and otherwise use Python + alone or in any derivative version, provided, however, that PSF's + License Agreement and PSF's notice of copyright, i.e., "Copyright (c) + 2001, 2002, 2003, 2004, 2005, 2006 Python Software Foundation; All Rights + Reserved" are retained in Python alone or in any derivative version + prepared by Licensee. + . + 3. In the event Licensee prepares a derivative work that is based on + or incorporates Python or any part thereof, and wants to make + the derivative work available to others as provided herein, then + Licensee hereby agrees to include in any such work a brief summary of + the changes made to Python. + . + 4. PSF is making Python available to Licensee on an "AS IS" + basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR + IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND + DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS + FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT + INFRINGE ANY THIRD PARTY RIGHTS. + . + 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON + FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS + A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, + OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + . + 6. This License Agreement will automatically terminate upon a material + breach of its terms and conditions. + . + 7. Nothing in this License Agreement shall be deemed to create any + relationship of agency, partnership, or joint venture between PSF and + Licensee. This License Agreement does not grant permission to use PSF + trademarks or trade name in a trademark sense to endorse or promote + products or services of Licensee, or any third party. + . + 8. By copying, installing or otherwise using Python, Licensee + agrees to be bound by the terms and conditions of this License + Agreement. diff --git a/gbp.conf b/gbp.conf new file mode 100644 index 0000000..cec628c --- /dev/null +++ b/gbp.conf @@ -0,0 +1,2 @@ +[DEFAULT] +pristine-tar = True diff --git a/python3-pyvisa.docs b/python3-pyvisa.docs new file mode 100644 index 0000000..e845566 --- /dev/null +++ b/python3-pyvisa.docs @@ -0,0 +1 @@ +README diff --git a/rules b/rules new file mode 100755 index 0000000..3fba670 --- /dev/null +++ b/rules @@ -0,0 +1,25 @@ +#!/usr/bin/make -f + +%: + dh $@ --with python3 --buildsystem=pybuild + +override_dh_auto_clean: + $(RM) -r PyVISA.egg-info + $(RM) -r build + dh_auto_clean + +#override_dh_auto_build: +# dh_auto_build +# set -ex; for python in $(shell py3versions -r); do \ +# $$python setup.py build; \ +# done + +#override_dh_auto_install: +# dh_auto_install +# set -ex; for python in $(shell py3versions -r); do \ +# $$python setup.py install --install-layout=deb \ +# --root $(CURDIR)/debian/tmp; \ +# done; + +override_dh_installchangelogs: + dh_installchangelogs -k CHANGES diff --git a/source/format b/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/upstream/metadata b/upstream/metadata new file mode 100644 index 0000000..57757e1 --- /dev/null +++ b/upstream/metadata @@ -0,0 +1,6 @@ +--- +Bug-Database: https://github.com/pyvisa/pyvisa/issues +Bug-Submit: https://github.com/pyvisa/pyvisa/issues/new +Name: pyvisa +Repository: https://github.com/pyvisa/pyvisa.git +Repository-Browse: https://github.com/pyvisa/pyvisa diff --git a/watch b/watch new file mode 100644 index 0000000..c427358 --- /dev/null +++ b/watch @@ -0,0 +1,2 @@ +version=3 +https://github.com/pyvisa/pyvisa/releases /pyvisa/pyvisa/archive/(\d\S+)\.tar\.(?:bz2|gz|xz) -- cgit v1.2.3