Initial Python3 build steps and test script

The increasing popularity of Python3 requires that Hamlib provide a
means of instruction for building and installing its module concurrent
with the Python2 module.  README.python outlines the required steps.
py3test.py is a reworking of the pytest.py script for Python3 syntax.
astyle-formatting
Nate Bargmann 2017-07-19 18:09:54 -05:00
rodzic 72a9bff55d
commit 6e3b79fc69
5 zmienionych plików z 358 dodań i 46 usunięć

3
NEWS
Wyświetl plik

@ -6,10 +6,11 @@ Copyright (C) 2000-2016 Stephane Fillod, and others
Please send Hamlib bug reports to hamlib-developer@lists.sourceforge.net
Version 3.2
2017-06-30
2017-08-31
* New models, IC-7850/IC-7851 in IC-785x. Mike, W9MDB
* Fix ft991_get_mode, Mike, W9MDB
* New model, FT-891. Mike, W9MDB
* Build instructions and test script for Python3
Version 3.1
2016-12-31

Wyświetl plik

@ -14,9 +14,10 @@ SWGDEP=$(top_srcdir)/include/hamlib/rig.h $(top_srcdir)/include/hamlib/riglist.h
$(SWGFILES)
EXTRA_DIST = $(SWGFILES) \
Makefile.PL perltest.pl tcltest.tcl pytest.py luatest.lua
Makefile.PL perltest.pl tcltest.tcl pytest.py py3test.py luatest.lua \
README.python
noinst_SCRIPTS = perltest.pl tcltest.tcl pytest.py hamlibvb.bas luatest.lua
noinst_SCRIPTS = perltest.pl tcltest.tcl pytest.py py3test.py hamlibvb.bas luatest.lua
BUILT_SOURCES=
MOSTLYCLEANFILES=

Wyświetl plik

@ -0,0 +1,169 @@
For several years the Python world has been in a state of transition from
version 2.x to 3.x. Much code still exists for Python2 in the form of
applications, modules, and packages and will likely be supported for some
time to come. Python3 is gaining acceptance, especially with new
development and many modules and packages are now available for Python3.
The Python developers have taken care to ensure that Python2 and Python3
and their respective modules and packages can be installed concurrently.
The steps below take advantage of this feature to install Hamlib.py modules
for both Python versions. Complete installation of each Python version
including their respective development files are required for successful
generation of the bindings by SWIG.
At this time the GNU Autotools do not offer a clean method of building SWIG
bindings for multiple versions of Python. Some hacks can be found on the
Web but until a clean native solution is offered the steps in this document
should prove adequate. With the wealth of Python2 programs, modules, and
packages still in use, it isn't likely to disappear from distributions
anytime soon. Python3 is becoming more popular for new development with a
complete standard library and many modules and packages being ported over
and available. It's time that we offer a means to generate bindings for
either version. This document will provide the steps for doing so.
NOTE: Developers and testers building from a Git clone/checkout will need
to bootstrap the build system by running the autogen.sh script. Source
releases and source daily snapshots already have this step completed.
NOTE: The commands assume an out of tree build in a sibling directory to
the main source directory. Adjust your paths accordingly. Adjust your
--prefix option as needed (installation to the user's home directory is
shown to avoid root privileges).
Asssuming that Python2 is the default installed Python interpreter, build
its bindings first:
../hamlib/configure --with-python-binding --prefix=$HOME/local
make
make install
At this point the Hamlib binaries, development files, and Python2 bindings
will be installed to their customary locations under $HOME/local.
Examination of the configure script's output will confirm that Python2 is
found and used as this extract shows:
checking whether to build python binding and demo... yes
checking for a Python interpreter with version >= 2.1... python
checking for python... /usr/bin/python
checking for python version... 2.7
checking for python platform... linux2
checking for python script directory... ${prefix}/lib64/python2.7/site-packages
checking for python extension module directory... ${exec_prefix}/lib64/python2.7/site-packages
checking for python2.7... (cached) /usr/bin/python
checking for a version of Python >= '2.1.0'... yes
checking for the distutils Python package... yes
checking for Python include path... -I/usr/include/python2.7
checking for Python library path... -L/usr/lib64 -lpython2.7
checking for Python site-packages path... /usr/lib64/python2.7/site-packages
checking python extra libraries... -lpthread -ldl -lutil
checking python extra linking flags... -Xlinker -export-dynamic
checking consistency of all components of python development environment... yes
At this point the file pytest.py in the source bindings directory may be
run as a test. If an error is given that the Hamlib module cannot be
found, see below.
The next step is to configure and build for Python3:
../hamlib/configure --with-python-binding PYTHON=`which python3` --prefix=$HOME/local
make
Here the PYTHON environment variable is set to the first python3 executable
found in the path (python3 may be a symbolic link, which is fine). This
may be unwanted behavior if multiple versions of Python are installed.
Python3 was found as shown in this configure output extract:
checking whether to build python binding and demo... yes
checking whether /usr/bin/python3 version is >= 2.1... yes
checking for /usr/bin/python3 version... 3.6
checking for /usr/bin/python3 platform... linux
checking for /usr/bin/python3 script directory... ${prefix}/lib64/python3.6/site-packages
checking for /usr/bin/python3 extension module directory... ${exec_prefix}/lib64/python3.6/site-packages
checking for python3.6... /usr/bin/python3
checking for a version of Python >= '2.1.0'... yes
checking for the distutils Python package... yes
checking for Python include path... -I/usr/include/python3.6m
checking for Python library path... -L/usr/lib64 -lpython3.6m
checking for Python site-packages path... /usr/lib64/python3.6/site-packages
checking python extra libraries... -lpthread -ldl -lutil
checking python extra linking flags... -Xlinker -export-dynamic
checking consistency of all components of python development environment... yes
Since all the Makefiles were regenerated by the second run of configure,
hamlib will be compiled again.
Next install the Python3 bindings:
cd bindings
make install
In this case, only the generated files in 'bindings' will be installed
which will be the new Python3 bindings.
Test that the Hamlib Python3 bindings are found by running the
bindings/py3test.py script.
At this point working bindings are installed and have been tested.
Running 'make uninstall' will only remove the version of the bindings that
was last configured. To uninstall the other version the respective options
will need to be passed to 'configure' and 'make uninstall' run again.
What to do if Python complains the module cannot be found.
There are various ways that a specific path can be provided to Python.
Perhaps the easiest is to provide an environment variable to your script.
Since Python will not have $HOME/local/... in its search path, here is an
example:
$ py3test.py
Traceback (most recent call last):
File "./py3test.py", line 9, in <module>
import Hamlib
ModuleNotFoundError: No module named 'Hamlib'
This isn't good! Let's set an environment variable for the running script:
PYTHONPATH=$HOME/local/lib64/python3.6/site-packages:$PYTHONPATH ./py3test.py
Success!
Like the standard PATH environment variable PYTHONPATH can contain multiple
paths separated by colons. In this case, if PYTHONPATH was already set the
new path is prepended to its prior setting.
While setting the environment variable is good for a one-off run, a more
permanent solution can be acheived by placing a file that ends in .pth in a
directory that Python will process when starting. The special place is:
~/.local/lib64/python3.6/site-packages
A .pth file must be set for each major.minor version of Python. Here is an
example for Python 2.7:
$HOME/.local/lib64/python2.7/site-packages/home.pth
Its content is simple:
/home/username/local/lib64/python2.7/site-packages
(These examples are from a Slackware box which installs Python modules into
the 'lib64' directory. Other distributions may simply use 'lib' or another
name.)
To verify the path, start the Python interpreter in interactive mode,
import the sys module, and check the value of sys.path. It will show a
number of paths in the list including the ones above and the directory the
interpreter was started from and various system directories.
Far more information than this is available in the relevant Python
documentation, but this should get your scripts working.
As always, feedback is welcome:
Hamlib Developers <hamlib-developer@lists.sourceforge.net>
73, Nate, N0NB

126
bindings/py3test.py 100755
Wyświetl plik

@ -0,0 +1,126 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
## Uncomment to run this script from an in-tree build (or adjust to the
## build directory) without installing the bindings.
#sys.path.append ('.')
#sys.path.append ('.libs')
import Hamlib
def StartUp():
"""Simple script to test the Hamlib.py module with Python3."""
print("%s: Python %s; %s\n" \
% (sys.argv[0], sys.version.split()[0], Hamlib.cvar.hamlib_version))
Hamlib.rig_set_debug(Hamlib.RIG_DEBUG_NONE)
# Init RIG_MODEL_DUMMY
my_rig = Hamlib.Rig(Hamlib.RIG_MODEL_DUMMY)
my_rig.set_conf("rig_pathname", "/dev/Rig")
my_rig.set_conf("retry", "5")
my_rig.open ()
# 1073741944 is token value for "itu_region"
# but using get_conf is much more convenient
region = my_rig.get_conf(1073741944)
rpath = my_rig.get_conf("rig_pathname")
retry = my_rig.get_conf("retry")
print("status(str):\t\t%s" % Hamlib.rigerror(my_rig.error_status))
print("get_conf:\t\tpath = %s, retry = %s, ITU region = %s" \
% (rpath, retry, region))
my_rig.set_freq(Hamlib.RIG_VFO_B, 5700000000)
my_rig.set_vfo(Hamlib.RIG_VFO_B)
print("freq:\t\t\t%s" % my_rig.get_freq())
my_rig.set_freq(Hamlib.RIG_VFO_A, 145550000)
(mode, width) = my_rig.get_mode()
print("mode:\t\t\t%s\nbandwidth:\t\t%s" % (Hamlib.rig_strrmode(mode), width))
my_rig.set_mode(Hamlib.RIG_MODE_CW)
(mode, width) = my_rig.get_mode()
print("mode:\t\t\t%s\nbandwidth:\t\t%s" % (Hamlib.rig_strrmode(mode), width))
print("ITU_region:\t\t%s" % my_rig.state.itu_region)
print("Backend copyright:\t%s" % my_rig.caps.copyright)
print("Model:\t\t\t%s" % my_rig.caps.model_name)
print("Manufacturer:\t\t%s" % my_rig.caps.mfg_name)
print("Backend version:\t%s" % my_rig.caps.version)
print("Backend license:\t%s" % my_rig.caps.copyright)
print("Rig info:\t\t%s" % my_rig.get_info())
my_rig.set_level("VOX", 1)
print("VOX level:\t\t%s" % my_rig.get_level_i("VOX"))
my_rig.set_level(Hamlib.RIG_LEVEL_VOX, 5)
print("VOX level:\t\t%s" % my_rig.get_level_i(Hamlib.RIG_LEVEL_VOX))
af = 12.34
print("Setting AF to %0.2f...." % (af))
my_rig.set_level("AF", af)
print("status:\t\t\t%s - %s" % (my_rig.error_status,
Hamlib.rigerror(my_rig.error_status)))
print("AF level:\t\t%s" % my_rig.get_level_f(Hamlib.RIG_LEVEL_AF))
print("strength:\t\t%s" % my_rig.get_level_i(Hamlib.RIG_LEVEL_STRENGTH))
print("status:\t\t\t%s" % my_rig.error_status)
print("status(str):\t\t%s" % Hamlib.rigerror(my_rig.error_status))
chan = Hamlib.channel(Hamlib.RIG_VFO_B)
my_rig.get_channel(chan)
print("get_channel status:\t%s" % my_rig.error_status)
print("VFO:\t\t\t%s, %s" % (Hamlib.rig_strvfo(chan.vfo), chan.freq))
print("Attenuators:\t\t%s" % my_rig.caps.attenuator)
print("\nSending Morse, '73'")
my_rig.send_morse(Hamlib.RIG_VFO_A, "73")
my_rig.close()
print("\nSome static functions:")
err, lon1, lat1 = Hamlib.locator2longlat("IN98XC")
err, lon2, lat2 = Hamlib.locator2longlat("DM33DX")
err, loc1 = Hamlib.longlat2locator(lon1, lat1, 3)
err, loc2 = Hamlib.longlat2locator(lon2, lat2, 3)
print("Loc1:\t\tIN98XC -> %9.4f, %9.4f -> %s" % (lon1, lat1, loc1))
print("Loc2:\t\tDM33DX -> %9.4f, %9.4f -> %s" % (lon2, lat2, loc2))
err, dist, az = Hamlib.qrb(lon1, lat1, lon2, lat2)
longpath = Hamlib.distance_long_path(dist)
print("Distance:\t%.3f km, azimuth %.2f, long path:\t%.3f km" \
% (dist, az, longpath))
# dec2dms expects values from 180 to -180
# sw is 1 when deg is negative (west or south) as 0 cannot be signed
err, deg1, mins1, sec1, sw1 = Hamlib.dec2dms(lon1)
err, deg2, mins2, sec2, sw2 = Hamlib.dec2dms(lat1)
lon3 = Hamlib.dms2dec(deg1, mins1, sec1, sw1)
lat3 = Hamlib.dms2dec(deg2, mins2, sec2, sw2)
print('Longitude:\t%4.4f, %4d° %2d\' %2d" %1s\trecoded: %9.4f' \
% (lon1, deg1, mins1, sec1, ('W' if sw1 else 'E'), lon3))
print('Latitude:\t%4.4f, %4d° %2d\' %2d" %1s\trecoded: %9.4f' \
% (lat1, deg2, mins2, sec2, ('S' if sw2 else 'N'), lat3))
if __name__ == '__main__':
StartUp()

Wyświetl plik

@ -1,82 +1,94 @@
#!/usr/bin/env python
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
import sys
sys.path.append ('.')
sys.path.append ('.libs')
## Uncomment to run this script from an in-tree build (or adjust to the
## build directory) without installing the bindings.
#sys.path.append ('.')
#sys.path.append ('.libs')
import Hamlib
def StartUp ():
print "Python", sys.version[:5], "test,", Hamlib.cvar.hamlib_version, "\n"
def StartUp():
"""Simple script to test the Hamlib.py module with Python2."""
#Hamlib.rig_set_debug (Hamlib.RIG_DEBUG_TRACE)
Hamlib.rig_set_debug (Hamlib.RIG_DEBUG_NONE)
print "%s: Python %s; %s\n" \
% (sys.argv[0], sys.version.split()[0], Hamlib.cvar.hamlib_version)
Hamlib.rig_set_debug(Hamlib.RIG_DEBUG_NONE)
# Init RIG_MODEL_DUMMY
my_rig = Hamlib.Rig (Hamlib.RIG_MODEL_DUMMY)
my_rig.set_conf ("rig_pathname","/dev/Rig")
my_rig.set_conf ("retry","5")
my_rig.set_conf("rig_pathname", "/dev/Rig")
my_rig.set_conf("retry", "5")
my_rig.open ()
my_rig.open()
# 1073741944 is token value for "itu_region"
# but using get_conf is much more convenient
region = my_rig.get_conf(1073741944)
rpath = my_rig.get_conf("rig_pathname")
retry = my_rig.get_conf("retry")
print "status(str):\t\t",Hamlib.rigerror(my_rig.error_status)
print "status(str):\t\t", Hamlib.rigerror(my_rig.error_status)
print "get_conf:\t\tpath = %s, retry = %s, ITU region = %s" \
% (rpath, retry, region)
% (rpath, retry, region)
my_rig.set_freq (Hamlib.RIG_VFO_B, 5700000000)
my_rig.set_vfo (Hamlib.RIG_VFO_B)
print "freq:\t\t\t",my_rig.get_freq()
my_rig.set_freq (Hamlib.RIG_VFO_A, 145550000)
#my_rig.set_vfo ("VFOA")
my_rig.set_freq(Hamlib.RIG_VFO_B, 5700000000)
my_rig.set_vfo(Hamlib.RIG_VFO_B)
print "freq:\t\t\t", my_rig.get_freq()
my_rig.set_freq(Hamlib.RIG_VFO_A, 145550000)
(mode, width) = my_rig.get_mode()
print "mode:\t\t\t",Hamlib.rig_strrmode(mode),"\nbandwidth:\t\t",width
print "mode:\t\t\t", Hamlib.rig_strrmode(mode), "\nbandwidth:\t\t", width
my_rig.set_mode(Hamlib.RIG_MODE_CW)
(mode, width) = my_rig.get_mode()
print "mode:\t\t\t",Hamlib.rig_strrmode(mode),"\nbandwidth:\t\t",width
print "ITU_region:\t\t",my_rig.state.itu_region
print "Backend copyright:\t",my_rig.caps.copyright
print "mode:\t\t\t", Hamlib.rig_strrmode(mode), "\nbandwidth:\t\t", width
print "Model:\t\t\t",my_rig.caps.model_name
print "Manufacturer:\t\t",my_rig.caps.mfg_name
print "Backend version:\t",my_rig.caps.version
print "Backend license:\t",my_rig.caps.copyright
print "ITU_region:\t\t", my_rig.state.itu_region
print "Backend copyright:\t", my_rig.caps.copyright
print "Model:\t\t\t", my_rig.caps.model_name
print "Manufacturer:\t\t", my_rig.caps.mfg_name
print "Backend version:\t", my_rig.caps.version
print "Backend license:\t", my_rig.caps.copyright
print "Rig info:\t\t", my_rig.get_info()
my_rig.set_level ("VOX", 1)
print "VOX level:\t\t",my_rig.get_level_i("VOX")
my_rig.set_level (Hamlib.RIG_LEVEL_VOX, 5)
my_rig.set_level("VOX", 1)
print "VOX level:\t\t", my_rig.get_level_i("VOX")
my_rig.set_level(Hamlib.RIG_LEVEL_VOX, 5)
print "VOX level:\t\t", my_rig.get_level_i(Hamlib.RIG_LEVEL_VOX)
af = 12.34
print "Setting AF to %f...." % (af)
my_rig.set_level ("AF", af)
print "status:\t\t\t%s - %s" % (my_rig.error_status, Hamlib.rigerror(my_rig.error_status))
print "AF level:\t\t", my_rig.get_level_f(Hamlib.RIG_LEVEL_AF)
print "Setting AF to %0.2f...." % (af)
my_rig.set_level ("AF", af)
print "status:\t\t\t%s - %s" % (my_rig.error_status,
Hamlib.rigerror(my_rig.error_status))
print "AF level:\t\t%0.2f" % my_rig.get_level_f(Hamlib.RIG_LEVEL_AF)
print "strength:\t\t", my_rig.get_level_i(Hamlib.RIG_LEVEL_STRENGTH)
print "status:\t\t\t",my_rig.error_status
print "status(str):\t\t",Hamlib.rigerror(my_rig.error_status)
print "status:\t\t\t", my_rig.error_status
print "status(str):\t\t", Hamlib.rigerror(my_rig.error_status)
chan = Hamlib.channel(Hamlib.RIG_VFO_B)
my_rig.get_channel(chan)
print "get_channel status:\t",my_rig.error_status
print "VFO:\t\t\t",Hamlib.rig_strvfo(chan.vfo),", ",chan.freq
print "get_channel status:\t", my_rig.error_status
print "VFO:\t\t\t", Hamlib.rig_strvfo(chan.vfo), ", ", chan.freq
print "Attenuators:\t\t", my_rig.caps.attenuator
print "\nSending Morse, '73'"
my_rig.send_morse(Hamlib.RIG_VFO_A, "73")
my_rig.send_morse(Hamlib.RIG_VFO_A, "73")
my_rig.close ()
print "\nSome static functions:"
@ -85,13 +97,15 @@ def StartUp ():
err, lon2, lat2 = Hamlib.locator2longlat("DM33DX")
err, loc1 = Hamlib.longlat2locator(lon1, lat1, 3)
err, loc2 = Hamlib.longlat2locator(lon2, lat2, 3)
print "Loc1:\t\tIN98XC -> %9.4f, %9.4f -> %s" % (lon1, lat1, loc1)
print "Loc2:\t\tDM33DX -> %9.4f, %9.4f -> %s" % (lon2, lat2, loc2)
err, dist, az = Hamlib.qrb(lon1, lat1, lon2, lat2)
longpath = Hamlib.distance_long_path(dist)
print "Distance:\t%.3f km, azimuth %.2f, long path:\t%.3f km" \
% (dist, az, longpath)
% (dist, az, longpath)
# dec2dms expects values from 180 to -180
# sw is 1 when deg is negative (west or south) as 0 cannot be signed
@ -102,10 +116,11 @@ def StartUp ():
lat3 = Hamlib.dms2dec(deg2, mins2, sec2, sw2)
print 'Longitude:\t%4.4f, %4d° %2d\' %2d" %1s\trecoded: %9.4f' \
% (lon1, deg1, mins1, sec1, ('W' if sw1 else 'E'), lon3)
% (lon1, deg1, mins1, sec1, ('W' if sw1 else 'E'), lon3)
print 'Latitude:\t%4.4f, %4d° %2d\' %2d" %1s\trecoded: %9.4f' \
% (lat1, deg2, mins2, sec2, ('S' if sw2 else 'N'), lat3)
% (lat1, deg2, mins2, sec2, ('S' if sw2 else 'N'), lat3)
if __name__ == '__main__':
StartUp ()
StartUp()