Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 80 additions & 1 deletion .github/workflows/ci-scripts-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ env:

jobs:
build-base:
name: ${{ matrix.base }}/${{ matrix.os }}/${{ matrix.python }}/${{ matrix.extra }}
name: ${{ matrix.base }}/${{ matrix.os }}/${{ matrix.profile }}/${{ matrix.python }}/${{ matrix.extra }}
runs-on: ${{ matrix.os }}
container: ${{ matrix.container }}
# Set environment variables from matrix parameters
env:
CMP: ${{ matrix.cmp }}
Expand All @@ -33,6 +34,49 @@ jobs:
base: "7.0"
python: "3.7"
profile: deb10
container: "python:3.7"
test: yes

- os: ubuntu-latest
cmp: gcc
configuration: default
base: "7.0"
python: "3.9"
profile: deb11
test: yes

- os: ubuntu-latest
cmp: gcc
configuration: default
base: "7.0"
python: "3.11"
profile: deb12
test: yes

- os: ubuntu-latest
cmp: gcc
configuration: default
base: "7.0"
python: "3.13"
profile: deb13
test: yes

- os: ubuntu-latest
cmp: gcc
configuration: default
base: "7.0"
python: "3.6"
container: "python:3.6"
profile: latest
test: yes

- os: ubuntu-latest
cmp: gcc
configuration: default
base: "7.0"
python: "3.7"
container: "python:3.7"
profile: latest
test: yes

- os: ubuntu-latest
Expand All @@ -59,6 +103,30 @@ jobs:
profile: latest
test: yes

- os: ubuntu-latest
cmp: gcc
configuration: default
base: "7.0"
python: "3.11"
profile: latest
test: yes

- os: ubuntu-latest
cmp: gcc
configuration: default
base: "7.0"
python: "3.12"
profile: latest
test: yes

- os: ubuntu-latest
cmp: gcc
configuration: default
base: "7.0"
python: "3.13"
profile: latest
test: yes

- os: macos-latest
cmp: gcc
configuration: default
Expand All @@ -72,20 +140,31 @@ jobs:
configuration: default
base: "3.15"
python: "3.7"
container: "python:3.7"
profile: deb10
test: yes

- os: ubuntu-latest
cmp: gcc
configuration: default
base: "3.15"
python: "3.13"
profile: deb13
test: yes

- os: ubuntu-latest
cmp: gcc
configuration: default
base: "3.14"
python: "3.7"
container: "python:3.7"
profile: deb10
steps:
- uses: actions/checkout@v3
with:
submodules: true
- name: Set up Python ${{ matrix.python }}
if: ${{ !matrix.container }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
Expand Down
4 changes: 2 additions & 2 deletions devsupApp/src/dbapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,11 +289,11 @@ static struct PyMethodDef dbapimethod[] = {

#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef dbapimodule = {
PyModuleDef_HEAD_INIT,
PyModuleDef_HEAD_INIT,
"devsup._dbapi",
NULL,
-1,
&dbapimethod
dbapimethod
};
#endif

Expand Down
30 changes: 19 additions & 11 deletions devsupApp/src/dbfield.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ static const int dbf2np_map[DBF_MENU+1] = {
NPY_INT16, // DBF_MENU
};
static PyArray_Descr* dbf2np[DBF_MENU+1];
#if NPY_ABI_VERSION < 0x02000000
#define PyDataType_ELSIZE(descr) ((descr)->elsize)
#define PyDataType_SET_ELSIZE(descr, size) (descr)->elsize = size
#endif
#endif

typedef struct {
Expand Down Expand Up @@ -98,10 +102,10 @@ static PyObject* build_array(PyObject* obj, void *data, unsigned short ftype, un

desc = dbf2np[ftype];
if(ftype==DBF_STRING) {
desc->elsize = MAX_STRING_SIZE;
PyDataType_SET_ELSIZE(desc, MAX_STRING_SIZE);
}

Py_XINCREF(desc);
Py_XINCREF(desc); // take a reference for PyArray_NewFromDescr() to steal
return PyArray_NewFromDescr(&PyArray_Type, desc, ndims, dims, NULL, data, flags, (PyObject*)obj);
#else
PyErr_SetNone(PyExc_NotImplementedError);
Expand All @@ -115,22 +119,25 @@ static int assign_array(DBADDR *paddr, PyObject *arr)
void *rawfield = paddr->pfield;
rset *prset;
PyObject *aval;
PyArrayObject *array = (PyArrayObject *)arr;
unsigned elemsize = dbValueSize(paddr->field_type);
unsigned long maxlen = paddr->no_elements, insize;
PyArray_Descr *desc = dbf2np[paddr->field_type];

if(paddr->field_type==DBF_STRING &&
(PyArray_NDIM(arr)!=2 || PyArray_DIM(arr,0)>maxlen || PyArray_DIM(arr,1)!=MAX_STRING_SIZE))
(PyArray_NDIM(array) != 2 ||
PyArray_DIM(array, 0) > (npy_intp) maxlen ||
PyArray_DIM(array, 1) != MAX_STRING_SIZE))
{
PyErr_Format(PyExc_ValueError, "String array has incorrect shape or is too large");
return 1;

} else if(PyArray_NDIM(arr)!=1 || PyArray_DIM(arr,0)>maxlen) {
} else if(PyArray_NDIM(array) != 1 || PyArray_DIM(array, 0) > (npy_intp) maxlen) {
PyErr_Format(PyExc_ValueError, "Array has incorrect shape or is too large");
return 1;
}

insize = PyArray_DIM(arr, 0);
insize = PyArray_DIM(array, 0);

if(paddr->special==SPC_DBADDR &&
(prset=dbGetRset(paddr)) &&
Expand All @@ -152,16 +159,17 @@ static int assign_array(DBADDR *paddr, PyObject *arr)
}

Py_XINCREF(desc);
if(!(aval = PyArray_FromAny(arr, desc, 1, 2, NPY_CARRAY, arr)))
if(!(aval = PyArray_FromAny(arr, desc, 1, 2, NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_ALIGNED | NPY_ARRAY_WRITEABLE, arr)))
return 1;

if(elemsize!=PyArray_ITEMSIZE(aval)) {
if(elemsize!=PyArray_ITEMSIZE((PyArrayObject *)aval)) {
PyErr_Format(PyExc_AssertionError, "item size mismatch %u %u",
elemsize, (unsigned)PyArray_ITEMSIZE(aval) );
elemsize, (unsigned)PyArray_ITEMSIZE((PyArrayObject *)aval));
Py_DECREF(aval);
return 1;
}

memcpy(rawfield, PyArray_GETPTR1(aval, 0), insize*elemsize);
memcpy(rawfield, PyArray_GETPTR1((PyArrayObject *)aval, 0), insize*elemsize);

Py_DECREF(aval);

Expand Down Expand Up @@ -207,7 +215,7 @@ static PyObject* pyField_getval(pyField *self)

if(self->addr.no_elements>1) {
return build_array((PyObject*)self, rawfield, self->addr.field_type,
noe, NPY_CARRAY_RO);
noe, NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_ALIGNED);
}
}

Expand Down Expand Up @@ -362,7 +370,7 @@ static PyObject *pyField_getarray(pyField *self)
} else
data = self->addr.pfield;

return build_array((PyObject*)self, data, self->addr.field_type, self->addr.no_elements, NPY_CARRAY);
return build_array((PyObject*)self, data, self->addr.field_type, self->addr.no_elements, NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_ALIGNED | NPY_ARRAY_WRITEABLE);
}

static PyObject *pyField_getlen(pyField *self)
Expand Down
14 changes: 7 additions & 7 deletions documentation/environment.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Runtime Environment
The pyDevSup module initializes the interpreter during the registration
phase of IOC startup with the *pySetupReg* registrar function. ::

#!../../bin/linux-x86_64/softIocPy2.7
#!../../bin/linux-x86_64/softIocPy3.6
# Interpreter not started
dbLoadDatabase("../../dbd/softIocPy.dbd",0,0)
softIocPy_registerRecordDeviceDriver(pdbbase)
Expand Down Expand Up @@ -51,7 +51,7 @@ file. ::

The default or preferred Python version can be specificed in *configure/CONFIG_SITE* ::

PY_VER ?= 2.7
PY_VER ?= 3.6

The following should be added to individual EPICS Makefiles. ::

Expand All @@ -64,8 +64,8 @@ The following should be added to individual EPICS Makefiles. ::

This will add or amend several make variables. The ``USR_*FLAGS`` variables
may be extended with appropriate flags for building python modules. The ``PY_VER``
variable is defined with the Python version number found in install directories (eg "2.7").
The ``PY_LD_VER`` variable is defined with the python library version number (eg "3.2mu"),
variable is defined with the Python version number found in install directories (eg "3.6").
The ``PY_LD_VER`` variable is defined with the python library version number (eg "3.6mu"),
which may be the same as ``PY_VER``.

Include pyDevSup in your IOC
Expand Down Expand Up @@ -113,11 +113,11 @@ Installing for several Python versions
The recipe for building and installing the pyDevSup module
for several python version side by side is ::

make PY_VER=2.6
make PY_VER=3.6
make clean
make PY_VER=2.7
make PY_VER=3.10
make clean
make PY_VER=3.2
make PY_VER=3.14
make clean

The ``PYTHON`` make variable can be specified if the interpreter executable
Expand Down
2 changes: 1 addition & 1 deletion documentation/gettingstarted.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ The :py:meth:`process <DeviceSupport.process>` method increments the *VAL* field

Start this IOC with. ::

$ ./bin/linux-x86_64/softIocPy2.7 -d cntrec.db
$ ./bin/linux-x86_64/softIocPy3.6 -d cntrec.db
Starting iocInit
...
iocRun: All initialization complete
Expand Down
2 changes: 1 addition & 1 deletion documentation/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pydevsup documentation

*pyDevSup* is a means of writing EPICS device support code in Python.

It currently supports EPICS >=3.14.12 and python versions: 2.7, and >=3.2.
It currently supports EPICS >=3.14.12 and python versions >=3.6
The numpy package is also required.

The source can be found at http://github.com/mdavidsaver/pyDevSup
Expand Down
2 changes: 1 addition & 1 deletion iocBoot/iocapplmon/st.cmd
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!../../bin/linux-x86/softIocPy2.7
#!../../bin/linux-x86/softIocPy3.6

< envPaths

Expand Down
2 changes: 1 addition & 1 deletion iocBoot/iocarchivemon/st.cmd
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!../../bin/linux-x86/softIocPy2.7
#!../../bin/linux-x86/softIocPy3.6

< envPaths

Expand Down
2 changes: 1 addition & 1 deletion iocBoot/iocarchivemon/st.cmd.main
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!../../bin/linux-x86_64/softIocPy2.7
#!../../bin/linux-x86_64/softIocPy3.6

< envPaths

Expand Down
23 changes: 19 additions & 4 deletions makehelper.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,30 @@
pass
out = open(sys.argv[1], 'w')

from distutils.sysconfig import get_config_var, get_python_inc
"""
3.2 sysconfig
3.10 sysconfig.get_path
3.10.13 distutils is deprecated.
3.12 distutils was removed.
"""
if sys.version_info >= (3,10,):
from sysconfig import get_config_var, get_path
incdirs = [get_path("include")]
else:
from distutils.sysconfig import get_config_var, get_python_inc
incdirs = [get_python_inc()]

incdirs = [get_python_inc()]
libdir = get_config_var('LIBDIR') or ''

have_np='NO'

"""
numpy 1.18, numpy.get_include()
"""
try:
from numpy.distutils.misc_util import get_numpy_include_dirs
incdirs = get_numpy_include_dirs()+incdirs
from numpy import get_include
numpy_dir = [get_include()]
incdirs = numpy_dir+incdirs
have_np='YES'
except ImportError:
pass
Expand Down
2 changes: 2 additions & 0 deletions requirements-deb11.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
numpy==1.19.5
nose2==0.9.2
2 changes: 2 additions & 0 deletions requirements-deb12.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
numpy==1.24.2
nose2==0.12.0
2 changes: 2 additions & 0 deletions requirements-deb13.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
numpy==2.2.4
nose2==0.15.1