diff --git a/.ci b/.ci new file mode 160000 index 00000000..fbbfced9 --- /dev/null +++ b/.ci @@ -0,0 +1 @@ +Subproject commit fbbfced900b5e87de9a176a68c40b8cafa3e8e01 diff --git a/.ci/build-deps.sh b/.ci/build-deps.sh deleted file mode 100755 index e1a3e14a..00000000 --- a/.ci/build-deps.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/sh -set -e -x - -CURDIR="$PWD" - -install -d "$HOME/.source" -cd "$HOME/.source" - -if [ "$BRPVA" ] -then - git clone --quiet --depth 5 --branch "$BRPVA" https://github.com/mdavidsaver/pvAccessCPP.git pvAccessCPP - (cd pvAccessCPP && git log -n1 ) - cat << EOF >> $CURDIR/configure/RELEASE.local -PVACCESS=$HOME/.source/pvAccessCPP -EOF - cat << EOF > pvAccessCPP/configure/RELEASE.local -PVDATA=$HOME/.source/pvDataCPP -EPICS_BASE=$HOME/.source/epics-base -EOF -fi - -if [ "$BRPVD" ] -then - git clone --quiet --depth 5 --branch "$BRPVD" https://github.com/epics-base/pvDataCPP.git pvDataCPP - (cd pvDataCPP && git log -n1 ) - cat << EOF >> $CURDIR/configure/RELEASE.local -PVDATA=$HOME/.source/pvDataCPP -EOF - cat << EOF > pvDataCPP/configure/RELEASE.local -EPICS_BASE=$HOME/.source/epics-base -EOF -fi - -if [ "$BRPVXS" ] -then - git clone --quiet --recursive --depth 5 --branch "$BRPVXS" https://github.com/epics-base/pvxs.git pvxs - (cd pvxs && git log -n1 ) - cat << EOF >> $CURDIR/configure/RELEASE.local -PVXS=$HOME/.source/pvxs -EOF - cat << EOF > pvxs/configure/RELEASE.local -EPICS_BASE=$HOME/.source/epics-base -EOF -fi - -git clone --quiet --depth 5 --branch "$BRBASE" https://github.com/epics-base/epics-base.git epics-base -(cd epics-base && git log -n1 ) - -cat << EOF >> $CURDIR/configure/RELEASE.local -EPICS_BASE=$HOME/.source/epics-base -EOF -cat $CURDIR/configure/RELEASE.local - -EPICS_HOST_ARCH=`sh epics-base/startup/EpicsHostArch` - -make -j2 -C epics-base "$@" -[ "$BRPVD" ] && make -j2 -C pvDataCPP "$@" -[ "$BRPVA" ] && make -j2 -C pvAccessCPP "$@" - -if [ "$BRPVXS" ] -then - make -j2 -C pvxs/bundle libevent "$@" - make -j2 -C pvxs "$@" -fi diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7f7678b2..2100aeb7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,492 +1,302 @@ -name: P4P +name: Python on: [push, pull_request, workflow_dispatch] +defaults: + run: + shell: bash + jobs: - build: - name: ${{ matrix.name }} + manylinux: + name: py${{ matrix.py }} ${{ matrix.ml }} + + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + # see compat matrix: https://github.com/pypa/manylinux + + - ml: manylinux1_x86_64 + py: cp27-cp27m + cy: "Cython<3.0" + numpy: numpy==1.8.2 + skip: true + + - ml: manylinux2014_x86_64 + py: cp38-cp38 + cy: "Cython<3.1" + numpy: numpy==1.17.3 + + - ml: manylinux2014_x86_64 + py: cp39-cp39 + numpy: numpy==1.21.6 # Highest supported on this piparch + + - ml: manylinux2014_x86_64 + py: cp310-cp310 + numpy: numpy==2.0.1 + + - ml: manylinux2014_x86_64 + py: cp311-cp311 + numpy: numpy==2.2.6 # Highest supported on this piparch + + - ml: manylinux2014_x86_64 + py: cp312-cp312 + numpy: numpy==2.2.6 # Highest supported on this piparch + + - ml: manylinux2014_x86_64 + py: cp313-cp313 + numpy: numpy==2.2.6 # Highest supported on this piparch + + - ml: manylinux2014_x86_64 + py: cp313-cp313t + numpy: numpy==2.2.6 # Highest supported on this piparch + + - ml: manylinux_2_28_x86_64 + py: cp314-cp314 + numpy: numpy==2.3.5 + + - ml: manylinux_2_28_x86_64 + py: cp314-cp314t + numpy: numpy==2.3.5 + src: true + + steps: + - uses: actions/checkout@v6 + with: + submodules: recursive + + - name: Automatic core dumper analysis + uses: mdavidsaver/ci-core-dumper@master + + - name: Detect pre-release + run: python ./gha-set-pre.py + + - name: Build + run: | + # emit script to be executed in container. + cat < runit.sh + #!/bin/sh + set -e -x + ls /opt/python/ + /opt/python/${{ matrix.py }}/bin/python --version + + yum -y install gdb || dnf -y install gdb || (apt update && apt -y install gdb) + + export PATH="/opt/python/${{ matrix.py }}/bin:\$PATH" + export SETUPTOOLS_DSO_PLAT_NAME="${{ matrix.ml }}" + + cd /io + + pip install -U pip + # pre-download for later steps + pip download $PRE -d output \ + --only-binary numpy,Cython \ + "${{ matrix.cy || 'Cython' }}" \ + "${{ matrix.numpy || 'numpy' }}" \ + setuptools_dso pvxslibs wheel ply nose2 + + # create source tar + pip install $PRE --no-index -f ./output setuptools_dso numpy Cython pvxslibs + python setup.py sdist -d ./output + ls -lh output + + # build wheel from source tar + pip wheel $PRE -w ./output --no-index -f ./output p4p + ls -lh output + + # install wheel for testing + pip install $PRE --no-index -f ./output p4p nose2 + + # switch away from root when running test to avoid inclusion in PYTHONPATH + cd output + python -m nose2 -v p4p + + EOF + # end of script. Now execute in container + + chmod +x runit.sh + mkdir output + podman run --rm \ + -v `pwd`:/io \ + quay.io/pypa/${{ matrix.ml }} \ + /io/runit.sh + + - name: Result + run: ls -lhtr output + + - name: Save wheels + if: ${{ ! matrix.skip }} + uses: actions/upload-artifact@v6 + with: + retention-days: 1 + name: whl-${{ matrix.py }}-${{ matrix.ml }} + path: output/p4p*.whl + + - name: Save source + if: ${{ matrix.src }} + uses: actions/upload-artifact@v6 + with: + retention-days: 1 + name: whl-source + path: output/p4p*.gz + + native: runs-on: ${{ matrix.os }} - env: - # used by .ci/build-deps.sh for Make builds - BRBASE: ${{ matrix.base }} - BRPVXS: ${{ matrix.pvxs }} strategy: fail-fast: false matrix: include: - # Linux Makefile builds - - name: Make Linux py3.x e7.0 - os: ubuntu-latest - python: "3.x" - base: "7.0" - pvxs: "master" - profile: latest - skip_cothread: yes - - - name: Make Linux py3.x e3.15 - os: ubuntu-latest - python: "3.x" - base: "3.15" - pvxs: "master" - profile: latest - skip_cothread: yes - - - name: Make Linux py3.x e3.14 - # https://github.com/epics-base/epics-base/issues/330 - os: ubuntu-latest - python: "3.x" - base: "3.14" - pvxs: "master" - profile: latest - skip_cothread: yes - - # Check build from .tar - - name: Source - os: ubuntu-latest - python: "3.12" - source: true - - # Linux py builds x64 - # TODO: manylinux1 and 2014 are EOL, even more reason to remove these supported versions - - name: linux 2.7 amd64 - os: ubuntu-latest - pyver: cp27-cp27m - piparch: manylinux1_x86_64 - numpy: numpy==1.8.2 - cython: Cython==0.29.2 - - - name: linux 2.7u amd64 - os: ubuntu-latest - pyver: cp27-cp27mu - piparch: manylinux1_x86_64 - numpy: numpy==1.8.2 - cython: Cython==0.29.2 - - - name: linux 3.5 amd64 - os: ubuntu-latest - pyver: cp35-cp35m - piparch: manylinux1_x86_64 - numpy: numpy==1.12.1 - cython: Cython==0.29.2 - - - name: linux 3.6 amd64 - os: ubuntu-latest - pyver: cp36-cp36m - piparch: manylinux1_x86_64 - numpy: numpy==1.12.1 - cython: Cython==0.29.2 - - - name: linux 3.7 amd64 - os: ubuntu-latest - pyver: cp37-cp37m - piparch: manylinux1_x86_64 - numpy: numpy==1.16.2 - cython: Cython==0.29.2 - - - name: linux 3.8 amd64 - os: ubuntu-latest - pyver: cp38-cp38 - piparch: manylinux1_x86_64 - numpy: numpy==1.17.3 - cython: Cython==0.29.14 - - - name: linux 3.9 amd64 - os: ubuntu-latest - pyver: cp39-cp39 - piparch: manylinux2010_x86_64 - numpy: numpy==1.21.6 # Highest supported on this piparch - cython: Cython==0.29.23 - - - name: linux 3.10 amd64 - os: ubuntu-latest - pyver: cp310-cp310 - piparch: manylinux2014_x86_64 - numpy: numpy==2.0.1 - cython: Cython==3.0.10 - - - name: linux 3.11 amd64 - os: ubuntu-latest - pyver: cp311-cp311 - piparch: manylinux2014_x86_64 - numpy: numpy==2.2.6 # Highest supported on this piparch - cython: Cython==3.0.10 - - - name: linux 3.12 amd64 - os: ubuntu-latest - pyver: cp312-cp312 - piparch: manylinux2014_x86_64 - numpy: numpy==2.2.6 # Highest supported on this piparch - cython: Cython==3.0.10 - skip_cothread: yes - - - name: linux 3.13 amd64 - os: ubuntu-latest - pyver: cp313-cp313 - piparch: manylinux2014_x86_64 - numpy: numpy==2.2.6 # Highest supported on this piparch - cython: Cython==3.0.10 - skip_cothread: yes - - # Linux py builds x64 - # TODO: manylinux1 and 2014 are EOL, even more reason to remove these supported versions - - name: linux 2.7 i686 - os: ubuntu-latest - pyver: cp27-cp27m - piparch: manylinux1_i686 - numpy: numpy==1.11.1 - cython: Cython==0.29.2 - pre: linux32 - - - name: linux 2.7u i686 - os: ubuntu-latest - pyver: cp27-cp27mu - piparch: manylinux1_i686 - numpy: numpy==1.11.1 - cython: Cython==0.29.2 - pre: linux32 - - - name: linux 3.5 i686 - os: ubuntu-latest - pyver: cp35-cp35m - piparch: manylinux1_i686 - numpy: numpy==1.12.1 - cython: Cython==0.29.2 - pre: linux32 - - - name: linux 3.6 i686 - os: ubuntu-latest - pyver: cp36-cp36m - piparch: manylinux1_i686 - numpy: numpy==1.12.1 - cython: Cython==0.29.2 - pre: linux32 - - - name: linux 3.7 i686 - os: ubuntu-latest - pyver: cp37-cp37m - piparch: manylinux1_i686 - numpy: numpy==1.16.2 - cython: Cython==0.29.2 - pre: linux32 - skip_cothread: yes - - - name: linux 3.8 i686 - os: ubuntu-latest - pyver: cp38-cp38 - piparch: manylinux1_i686 - numpy: numpy==1.19.5 - cython: Cython==0.29.14 - pre: linux32 - skip_cothread: yes - - - name: linux 3.9 i686 - os: ubuntu-latest - pyver: cp39-cp39 - piparch: manylinux2010_i686 + - os: windows-latest + py: "3.8" + cy: "Cython<3.1" numpy: numpy==1.19.5 - cython: Cython==0.29.23 - pre: linux32 - skip_cothread: yes - - # numpy i386 wheels not built >= 3.10 - - # OSX py builds - - name: osx 3.6 intel - os: macos-13 - python: "3.6" - piparch: macosx_10_9_intel - numpy: numpy==1.11.3 - cython: Cython==0.29.2 - - - name: osx 3.7 intel - os: macos-13 - python: "3.7" - piparch: macosx_10_9_intel - numpy: numpy==1.16.2 - cython: Cython==0.29.2 - - - name: osx 3.8 arm64 - os: macos-latest - python: "3.8" - piparch: macosx_11_0_universal2 - numpy: numpy==1.24.4 - cython: Cython==0.29.15 - skip_cothread: yes + arch: win_amd64 - - name: osx 3.9 arm64 - os: macos-latest - python: "3.9" - piparch: macosx_11_0_universal2 - numpy: numpy==2.0.1 - cython: Cython==3.0.10 - skip_cothread: yes + # windows + 3.9 omitted due to numpy bug "invalid preprocessor command 'warning'" - - name: osx 3.10 arm64 - os: macos-latest - python: "3.10" - piparch: macosx_11_0_universal2 + - os: windows-latest + py: "3.10" numpy: numpy==2.2.6 - cython: Cython==3.0.10 - skip_cothread: yes + arch: win_amd64 - - name: osx 3.11 arm64 - os: macos-latest - python: "3.11" - piparch: macosx_11_0_universal2 + - os: windows-latest + py: "3.11" numpy: numpy==2.3.1 - cython: Cython==3.0.10 - skip_cothread: yes + arch: win_amd64 - - name: osx 3.12 arm64 - os: macos-latest - python: "3.12" - piparch: macosx_11_0_universal2 + - os: windows-latest + py: "3.12" numpy: numpy==2.3.1 - cython: Cython==3.0.10 - skip_cothread: yes - - # Blocked on issue #179 - crash when running tests - # - name: osx 3.13 arm64 - # os: macos-latest - # python: "3.13" - # piparch: macosx_11_0_universal2 - # numpy: numpy==2.3.1 - # cython: Cython==3.0.10 - # skip_cothread: yes - - # Windows py builds - - - name: win64 3.6 - os: windows-latest - python: "3.6" - piparch: win_amd64 - numpy: numpy==1.12.1 - cython: Cython==0.29.2 - skip_cothread: yes - - - name: win64 3.7 - os: windows-latest - python: "3.7" - piparch: win_amd64 - numpy: numpy==1.16.2 - cython: Cython==0.29.2 - skip_cothread: yes - - - name: win64 3.8 - os: windows-latest - python: "3.8" - piparch: win_amd64 - numpy: numpy==1.19.5 - cython: Cython==0.29.14 - skip_cothread: yes + arch: win_amd64 - - name: win64 3.9 - os: windows-latest - python: "3.9" - piparch: win_amd64 - numpy: numpy==1.19.5 - cython: Cython==0.29.23 - skip_cothread: yes + - os: windows-latest + py: "3.13" + numpy: numpy==2.3.1 + arch: win_amd64 + + - os: windows-latest + py: "3.14" + numpy: numpy==2.3.5 + arch: win_amd64 - - name: win64 3.10 - os: windows-latest - python: "3.10" - piparch: win_amd64 + - os: macos-latest + py: "3.8" + cy: "Cython<3.1" + numpy: numpy==1.24.4 + arch: macosx_11_0_universal2 + + - os: macos-latest + py: "3.9" + numpy: numpy==2.0.1 + arch: macosx_11_0_universal2 + + - os: macos-latest + py: "3.10" numpy: numpy==2.2.6 - cython: Cython==3.0.10 - skip_cothread: yes + arch: macosx_11_0_universal2 - - name: win64 3.11 - os: windows-latest - python: "3.11" - piparch: win_amd64 + - os: macos-latest + py: "3.11" numpy: numpy==2.3.1 - cython: Cython==3.0.10 - skip_cothread: yes + arch: macosx_11_0_universal2 - - name: win64 3.12 - os: windows-latest - python: "3.12" - piparch: win_amd64 + - os: macos-latest + py: "3.12" numpy: numpy==2.3.1 - cython: Cython==3.0.10 - skip_cothread: yes + arch: macosx_11_0_universal2 - - name: win64 3.13 - os: windows-latest - python: "3.13" - piparch: win_amd64 + - os: macos-latest + py: "3.13" numpy: numpy==2.3.1 - cython: Cython==3.0.10 - skip_cothread: yes + arch: macosx_11_0_universal2 + + - os: macos-latest + py: "3.14" + numpy: numpy==2.3.5 + arch: macosx_11_0_universal2 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v6 with: - submodules: recursive + submodules: recursive - - name: Setup native python - if: matrix.python - uses: actions/setup-python@v5 + - uses: actions/setup-python@v6 with: - python-version: ${{ matrix.python }} - #architecture: x64 + python-version: ${{ matrix.py }} - # TLS 1.0 and 1.1 support was removed from pypi so the cached pip won't work - - name: Python 3.5 Fix - if: ${{ matrix.python == '3.5' }} - run: | - curl https://bootstrap.pypa.io/pip/3.5/get-pip.py | python + - name: Prepare + run: python -m pip install -U pip virtualenv - - name: Automatic core dumper analysis - uses: mdavidsaver/ci-core-dumper@master + - name: PIP Debug + run: pip debug -v - - name: Install Twine - if: true && !matrix.base - run: | - python -m pip install "twine<=6.0.1" - python -m twine -h - python ./gha-set-pre.py + - name: Detect pre-release + run: python ./gha-set-pre.py - - name: Native Prep/Info + - name: Build run: | - python -m pip install --upgrade pip - python -m pip install setuptools wheel twine - which python - python --version - python -m pip --version - python -m twine -h - python ./gha-set-pre.py + set -x -e + python -m pip install -U pip + pip download $PRE -d output \ + --only-binary numpy,Cython \ + "${{ matrix.cy || 'Cython' }}" \ + "${{ matrix.numpy || 'numpy' }}" \ + setuptools_dso pvxslibs wheel ply nose2 - - name: apt-get install - if: runner.os=='Linux' && matrix.base - run: | - sudo apt-get update - sudo apt-get -y install libreadline6-dev libncurses5-dev perl + export SETUPTOOLS_DSO_PLAT_NAME=${{ matrix.arch }} - - name: Native Deps - if: true && !matrix.pyver - shell: bash - run: | - if [ "${{ matrix.profile }}" ] - then - python -m pip install --only-binary numpy,numpy,Cython -r requirements-${{ matrix.profile }}.txt - else - python -m pip install --only-binary numpy,numpy,Cython nose2 ply ${{ matrix.numpy }} ${{ matrix.cython }} - fi - if [ "${{ matrix.skip_cothread }}" != "yes" ] - then - python -m pip install cothread - fi - - - name: PY Source - shell: bash - run: | - echo "PRE=$PRE" - python -m pip install setuptools wheel nose2 - python -m pip install --only-binary numpy $PRE setuptools-dso epicscorelibs pvxslibs - python setup.py sdist --formats=gztar - ls dist/* - - - name: Native Make build - if: matrix.base - run: | - ./.ci/build-deps.sh -j2 - make PYTHON=`which python` -j2 - python -m ci_core_dumper exec make PYTHON=`which python` nose + pip install $PRE --no-index -f ./output setuptools_dso numpy Cython pvxslibs + python setup.py sdist -d ./output + ls -lh output - - name: PEP517 Build - if: matrix.python && !matrix.base && matrix.source - run: | - python -m pip wheel -v -w dist $PRE dist/*.tar.* + # build wheel from source tar + pip wheel $PRE -w ./output --no-index -f ./output p4p + ls -lh output - - name: Native PY build - if: matrix.python && !matrix.base && !matrix.source - shell: bash - run: | - python -m pip wheel -v -w dist --no-index --no-deps \ - --no-build-isolation --no-use-pep517 \ - --build-option --plat-name=${{ matrix.piparch }} \ - $PRE \ - dist/*.tar.* - - cd dist - python -m pip install p4p*.whl - python -m ci_core_dumper exec python -m nose2 -v p4p - - - name: Docker PY build - if: matrix.pyver && !matrix.base && !matrix.source - run: | - # can't use GHA native docker support since GHA magic binaries need .so absent from old manylinux images :( - cat < runit.sh - #!/bin/sh - set -e -x - cd /io - [ -d dist ] - ls dist/* - export PATH="/opt/python/${{ matrix.pyver }}/bin:\$PATH" - which python - python -m pip install -U pip - python -m pip install setuptools wheel nose2 - python -m pip install --only-binary numpy $PRE setuptools-dso epicscorelibs pvxslibs - if [ "${{ matrix.profile }}" ] - then - python -m pip install --only-binary numpy,numpy,Cython -r requirements-${{ matrix.profile }}.txt - else - python -m pip install --only-binary numpy,numpy,Cython nose2 ply ${{ matrix.numpy }} ${{ matrix.cython }} - fi - if [ "${{ matrix.skip_cothread }}" != "yes" ] - then - python -m pip install cothread - fi - - python -m pip wheel -v -w dist --no-index --no-deps \ - --no-build-isolation --no-use-pep517 \ - --build-option --plat-name=${{ matrix.piparch }} \ - $PRE \ - dist/*.tar.* - - cd dist - python -m pip install --only-binary numpy p4p*.whl - python -m nose2 -v p4p - - EOF - cat runit.sh - chmod +x runit.sh - docker pull quay.io/pypa/${{ matrix.piparch }} - docker run --rm -v `pwd`:/io quay.io/pypa/${{ matrix.piparch }} ${{ matrix.pre }} /io/runit.sh - - - name: List Artifacts - if: true && !matrix.base - run: ls dist/* - - - name: Save Artifacts - if: true && !matrix.base - uses: actions/upload-artifact@v4 + # install wheel for testing + pip install $PRE --no-index -f ./output p4p nose2 + + # switch away from root when running test to avoid inclusion in PYTHONPATH + cd output + python -m nose2 -v p4p + + - run: ls -lhtr output + + - name: Save wheels + if: ${{ ! matrix.skip }} + uses: actions/upload-artifact@v6 with: - name: "p4p ${{ matrix.name }}" - path: dist/* + retention-days: 1 + name: whl-${{ matrix.py }}-${{ matrix.os }} + path: output/p4p*.whl - - name: Check wheels - if: ${{ !matrix.base && !matrix.source }} - run: python -m twine check dist/p4p*.whl + combine: + runs-on: ubuntu-latest + needs: [manylinux, native] + steps: + - name: Download + uses: actions/download-artifact@v7 + with: + merge-multiple: true - - name: Check source - if: ${{ matrix.source && !matrix.base }} - run: python -m twine check dist/p4p*.tar.* + - run: ls -lhtr - - name: Upload wheels - if: github.event_name=='push' && github.repository=='epics-base/p4p' && github.ref=='refs/heads/master' && !matrix.base && !matrix.source - env: - TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} - TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + - uses: actions/setup-python@v6 + with: + python-version: 3.11 + + - name: Setup run: | - python -m twine upload --skip-existing dist/p4p*.whl + pip install -U pip twine + python -m twine -h + + - name: Check + run: twine check p4p*.gz p4p*.whl - - name: Upload source - if: github.event_name=='push' && github.repository=='epics-base/p4p' && github.ref=='refs/heads/master' && matrix.source && !matrix.base + - name: Upload wheels + if: env.TWINE_USERNAME && github.event_name=='push' && github.ref=='refs/heads/master' env: TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} - run: | - python -m twine upload --skip-existing dist/p4p*.tar.* + run: twine upload --skip-existing p4p*.gz p4p*.whl diff --git a/.github/workflows/ci-scripts.yml b/.github/workflows/ci-scripts.yml new file mode 100644 index 00000000..7ddb1803 --- /dev/null +++ b/.github/workflows/ci-scripts.yml @@ -0,0 +1,126 @@ +name: Makefile + +on: [push, pull_request, workflow_dispatch] + +defaults: + run: + shell: bash + +env: + SETUP_PATH: .ci-local:.ci + +jobs: + make: + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + cmp: gcc + base: "7.0" + py: "3.8" + + - os: ubuntu-latest + cmp: gcc + base: "7.0" + py: "3.x" + + - os: windows-latest + cmp: vs2022 + base: "7.0" + py: "3.8" + + - os: windows-latest + cmp: vs2022 + base: "7.0" + py: "3.x" + + - os: macos-latest + cmp: clang + base: "7.0" + py: "3.8" + + - os: macos-latest + cmp: clang + base: "7.0" + py: "3.x" + + env: + MODULES: "pvxs" + BASE: ${{ matrix.base }} + BASE_RECURSIVE: NO + PVXS: master + PVXS_REPOOWNER: epics-base + CMP: ${{ matrix.cmp }} + BCFG: default + TEST: ${{ matrix.test }} + EXTRA: ${{ matrix.extra }} + + steps: + - uses: actions/checkout@v6 + with: + submodules: recursive + + - name: Automatic core dumper analysis + uses: mdavidsaver/ci-core-dumper@ci + + - name: "apt-get install" + if: runner.os == 'Linux' + run: | + sudo apt-get update + sudo apt-get -y install libreadline-dev g++-mingw-w64-x86-64 cmake gdb qemu-system-x86 libevent-dev + + - name: "brew libevent" + if: runner.os == 'macOS' + run: | + brew install libevent + echo "LIBEVENT=$(brew --prefix)" >> "$GITHUB_ENV" + + - name: "vcpkg cache" + if: runner.os == 'Windows' + uses: actions/cache@v4 + with: + path: c:/vcpkg-cache + key: ${{ runner.os }}-vcpkg + + - name: "vcpkg build" + if: runner.os == 'Windows' + shell: bash + run: | + install -d c:/vcpkg-cache + vcpkg install --binarysource="clear;files,c:/vcpkg-cache,readwrite" "libevent" + ls C:/vcpkg/installed/x64-windows + echo "LIBEVENT=C:/vcpkg/installed/x64-windows" >> "$GITHUB_ENV" + + - uses: actions/setup-python@v6 + with: + python-version: ${{ matrix.py }} + + - name: Inspect + shell: bash + run: find "$Python_ROOT_DIR" + + - name: get_config_vars + run: python -c 'import sysconfig, pprint; pprint.pprint(sysconfig.get_config_vars())' + + - name: Prepare and compile dependencies + run: python .ci/cue.py prepare + + - name: Py Deps + run: | + pip install -U pip + pip install Cython numpy ply nose2 + + - name: Build main module + run: python .ci/cue.py build + + - name: List + shell: bash + run: find python* -type f + + - name: Test + # "make nose" not yet working on Windows. + if: runner.os != 'Windows' + run: python .ci/cue.py build nose diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..cfa3a703 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule ".ci"] + path = .ci + url = https://github.com/epics-base/ci-scripts diff --git a/MANIFEST.in b/MANIFEST.in index d0d2abde..7965c869 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,8 +2,6 @@ include pyproject.toml include README.md include src/*.h include src/*.cpp -include src/p4p/*.h -include src/p4p/*.cpp include src/p4p/*.pyx include src/p4p/*.pxd include src/p4p/pvxs/*.pxd diff --git a/configure/CONFIG_PY b/configure/CONFIG_PY index 8d615d19..6904e90d 100644 --- a/configure/CONFIG_PY +++ b/configure/CONFIG_PY @@ -23,6 +23,15 @@ PROD_DEPLIB_DIRS += $(PY_LIBDIRS) INCLUDES += $(PY_INCDIRS:%=-I%) +# pyconfig.h emits eg. +# pragma comment(lib,"python311.lib") +# so no need to explicitly mention pythonX.Y.lib . +# However, must emit /LIBPATH with correct directory +ifeq ($(CMPLR_CLASS),msvc) +# no used as of 7.0.10 +#LOADABLE_SHRLIB_LDFLAGS += /LIBPATH:$(PY_LIBDIRS) +LIB_LDFLAGS += /LIBPATH:$(PY_LIBDIRS) +endif #LIB_SYS_LIBS += python$(PY_LD_VER) #PROD_SYS_LIBS += python$(PY_LD_VER) diff --git a/documentation/conf.py b/documentation/conf.py index 81662b00..2f801b01 100644 --- a/documentation/conf.py +++ b/documentation/conf.py @@ -58,7 +58,7 @@ # The short X.Y version. version = '4.2' # The full version, including alpha/beta/rc tags. -release = '4.2.1' +release = '4.2.2a1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/documentation/gw.rst b/documentation/gw.rst index 4c62ade5..8b663066 100644 --- a/documentation/gw.rst +++ b/documentation/gw.rst @@ -270,6 +270,11 @@ Here is a full list of JSON keys available for the configuration file, version 2 **clients[].bcastport** (default: 5076) UDP port to which searches are sent. +**cilents[].EPICS_PVA_\*** + Keys beginning with ``EPICS_PVA_`` are passed through verbatim, + and interpreted in the same manner as ``$EPICS_PVA_*`` environment variables. + Effects only one client instance. + **servers** List of gateway Server configurations. @@ -328,6 +333,10 @@ Here is a full list of JSON keys available for the configuration file, version 2 Unambiguously selects which client is used to connect ``INP`` PVs for use by conditional ACF rules. If not provided, then the first client in the list is used. +**servers[].EPICS_PVA\*** + Keys beginning with ``EPICS_PVA`` are interpreted in the same manner as ``$EPICS_PVA*`` environment variables. + Effects only one server instance. + .. _gwstatuspvs: Status PVs diff --git a/makehelper.py b/makehelper.py index d25e158d..a6c60892 100644 --- a/makehelper.py +++ b/makehelper.py @@ -13,7 +13,6 @@ from __future__ import print_function import sys -import errno import os if len(sys.argv)<2: @@ -32,8 +31,16 @@ def get_python_inc(): except ImportError: from distutils.sysconfig import get_config_var, get_python_inc +def gcv(name, *dflt): + v = get_config_var(name) + if v is None: + if len(dflt): + return dflt[0] + raise KeyError(name) + return v + incdirs = [get_python_inc()] -libdir = get_config_var('LIBDIR') or '' +libdir = gcv('LIBDIR', '') or gcv('prefix') + '/libs' def get_numpy_include_dirs(): @@ -44,14 +51,15 @@ def get_numpy_include_dirs(): incdirs = get_numpy_include_dirs() + incdirs -print('TARGET_CFLAGS +=',get_config_var('BASECFLAGS'), file=out) -print('TARGET_CXXFLAGS +=',get_config_var('BASECFLAGS'), file=out) +target_flags = gcv('BASECFLAGS', '') +print('TARGET_CFLAGS +=',target_flags, file=out) +print('TARGET_CXXFLAGS +=',target_flags, file=out) -print('PY_VER :=',get_config_var('VERSION'), file=out) -ldver = get_config_var('LDVERSION') +print('PY_VER :=',gcv('VERSION'), file=out) +ldver = gcv('LDVERSION', None) if ldver is None: - ldver = get_config_var('VERSION') - if get_config_var('Py_DEBUG'): + ldver = gcv('VERSION') + if gcv('Py_DEBUG', ''): ldver = ldver+'_d' print('PY_LD_VER :=',ldver, file=out) print('PY_INCDIRS :=',' '.join(incdirs), file=out) diff --git a/pyproject.toml b/pyproject.toml index 6286f501..bc702557 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,9 @@ requires = [ "setuptools_dso>=2.11a2; python_version>='3.12'", "wheel", "numpy>=1.7", - "Cython>=0.20", + "Cython>0.29.32, <3.0.0a1 ; python_version<'3.0'", + "Cython>0.29.32, <3.1.0a1 ; python_version>='3.0' and python_version<'3.9'", + "Cython>0.29.32 ; python_version>='3.9'", "epicscorelibs>=7.0.3.99.2.0a1", "epicscorelibs>=7.0.7.99.1.2a2; python_version>='3.12'", "pvxslibs>=1.3.1", diff --git a/src/Makefile b/src/Makefile index a599ec7c..72708f4f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -132,12 +132,12 @@ pvxs_client$(OBJ): _p4p.h ifneq (,$(T_A)) nose.%: - PYTHONPATH="${PYTHONPATH}:$(abspath $(TOP))/python$(PY_LD_VER)/$(T_A)" $(PYTHON) -m nose2 -v $* $(NOSEFLAGS) + cd "$(abspath $(TOP))/python$(PY_LD_VER)/$(T_A)" && $(PYTHON) -m nose2 -v $* $(NOSEFLAGS) # bounce back down to the sphinx generated Makefile # aren't Makefiles fun... sphinx: - PYTHONPATH="${PYTHONPATH}:$(abspath $(TOP))/python$(PY_LD_VER)/$(T_A)" $(MAKE) -C $(TOP)/documentation html + cd "$(abspath $(TOP))/python$(PY_LD_VER)/$(T_A)" && $(MAKE) -C $(TOP)/documentation html sh: echo "export PYTHONPATH=\$${PYTHONPATH}:$(abspath $(TOP))/python$(PY_LD_VER)/$(T_A)" $(if $(OUTPUT),> $(OUTPUT)) diff --git a/src/p4p/_gw.pyx b/src/p4p/_gw.pyx index 0efa72a0..fc4e5383 100644 --- a/src/p4p/_gw.pyx +++ b/src/p4p/_gw.pyx @@ -348,7 +348,7 @@ cdef public: except: return GWSearchBanHost - shared_ptr[GWChan] GWProvider_makeChannel(GWSource* src, unique_ptr[ChannelControl]* op) with gil: + shared_ptr[GWChan] GWProvider_makeChannel(GWSource* src, unique_ptr[ChannelControl]* op) noexcept with gil: cdef shared_ptr[GWChan] ret cdef CreateOp create if not src.handler: @@ -371,7 +371,7 @@ cdef public: return ret - void GWProvider_audit(GWSource* src, listxx[string]& cmsgs) with gil: + void GWProvider_audit(GWSource* src, listxx[string]& cmsgs) noexcept with gil: if src.handler: handler = src.handler msgs = [msg.decode() for msg in cmsgs] diff --git a/src/p4p/_p4p.pyx b/src/p4p/_p4p.pyx index 691548e3..348c7590 100644 --- a/src/p4p/_p4p.pyx +++ b/src/p4p/_p4p.pyx @@ -42,7 +42,7 @@ cdef extern from "" namespace "p4p": object tostr(const data.Value& v, size_t limit, bool showval) except+ # pvxs_sharedpv.cpp - string toString(const server.Server& serv, int detail) nogil except+ + string toString(const server.Server& serv, int detail) except+ nogil void attachHandler(sharedpv.SharedPV& pv, object handler) except+ void detachHandler(sharedpv.SharedPV& pv) except+ void attachCleanup(const shared_ptr[source.ExecOp]& op, object handler) except+ diff --git a/src/p4p/gw.py b/src/p4p/gw.py index 6baff174..14a682df 100644 --- a/src/p4p/gw.py +++ b/src/p4p/gw.py @@ -556,6 +556,9 @@ def __init__(self, args): client_conf['EPICS_PVA_BROADCAST_PORT'] = str(jcli['bcastport']) if 'serverport' in jcli: client_conf['EPICS_PVA_SERVER_PORT'] = str(jcli['serverport']) + for k,v in jcli.items(): # pass through + if k.startswith('EPICS_PVA_'): + client_conf[k] = v _log.info( "Client effective configuration for %s:", name) for confKeys, confVals in client_conf.items(): @@ -626,6 +629,9 @@ def __init__(self, args): server_conf['EPICS_PVAS_BROADCAST_PORT'] = str(jsrv['bcastport']) if 'serverport' in jsrv: server_conf['EPICS_PVAS_SERVER_PORT'] = str(jsrv['serverport']) + for k,v in jsrv.items(): # pass through + if k.startswith('EPICS_PVA'): + server_conf[k] = v # pick client to use for ACF INP* aclient = jsrv.get('acf_client') diff --git a/src/p4p/pvxs/data.pxd b/src/p4p/pvxs/data.pxd index 6720719e..65211b5c 100644 --- a/src/p4p/pvxs/data.pxd +++ b/src/p4p/pvxs/data.pxd @@ -93,7 +93,7 @@ cdef extern from "" namespace "pvxs" nogil: cdef cppclass TypeDef: TypeDef() TypeDef(const TypeDef&) - TypeDef(TypeDef&&) +# TypeDef(TypeDef&&) TypeDef(const Value&) except+ @@ -108,7 +108,7 @@ cdef extern from "" namespace "pvxs" nogil: cdef cppclass Value: Value() Value(const Value&) - Value(Value&&) +# Value(Value&&) Value cloneEmpty() except+ Value clone() except+ diff --git a/src/p4p/pvxs/sharedArray.pxd b/src/p4p/pvxs/sharedArray.pxd index 09a9d228..521c4b96 100644 --- a/src/p4p/pvxs/sharedArray.pxd +++ b/src/p4p/pvxs/sharedArray.pxd @@ -25,7 +25,7 @@ cdef extern from "" namespace "pvxs" nogil: cdef cppclass shared_array[T]: shared_array() shared_array(const shared_array&) - shared_array(shared_array&&) +# shared_array(shared_array&&) shared_array(size_t cnt) except+ shared_array(T*, size_t) diff --git a/src/p4p/version.py b/src/p4p/version.py index 6a2c4779..bf951264 100644 --- a/src/p4p/version.py +++ b/src/p4p/version.py @@ -67,4 +67,4 @@ def __ge__(self, o): def __gt__(self, o): return self._cmp(o)>0 -version = Version('4.2.1') +version = Version('4.2.2a1')