Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make pythonIoc pip installable #5

Merged
merged 19 commits into from
Jun 23, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
46 changes: 29 additions & 17 deletions .github/workflows/code.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,36 @@ jobs:
os: [ubuntu-latest, windows-latest, macos-latest]
python: [cp27, cp37, cp38, cp39]

include:
- os: macos-latest
TEST_REQUIRES: pytest-cov cothread
# Put coverage straight in the dist dir
COV_FILE: '{project}/dist/coverage.xml'
exclude:
- os: windows-latest
# No cothread or asyncio so doesn't work
python: cp27

include:
- os: ubuntu-latest
TEST_REQUIRES: pytest-cov cothread
# Put coverage in the output dir mounted in docker
COV_FILE: '/output/coverage.xml'
cov_file: /output/coverage.xml
test_requires: cothread pytest-asyncio aioca

- os: windows-latest
cov_file: '{project}/dist/coverage.xml'
# cothread doesn't work on windows
TEST_REQUIRES: pytest-cov
# Put coverage straight in the dist dir
COV_FILE: '{project}/dist/coverage.xml'
test_requires: pytest-asyncio aioca

- os: macos-latest
cov_file: '{project}/dist/coverage.xml'
test_requires: cothread pytest-asyncio aioca

- os: ubuntu-latest
python: cp27
# asyncio doesn't work on Python2.7
test_requires: cothread

- os: macos-latest
python: cp27
# asyncio doesn't work on Python2.7
test_requires: cothread


steps:
- name: Checkout Source
Expand All @@ -70,15 +84,16 @@ jobs:
run: cibuildwheel --output-dir dist
env:
CIBW_BUILD: ${{ matrix.python }}*64
CIBW_TEST_REQUIRES: ${{ matrix.TEST_REQUIRES }}
CIBW_TEST_COMMAND: pytest --cov=softioc {project}/tests --cov-report xml:${{ matrix.COV_FILE }}
CIBW_TEST_REQUIRES: pytest-cov ${{ matrix.test_requires }}
CIBW_TEST_COMMAND: pytest --cov=softioc {project}/tests --cov-report xml:${{ matrix.cov_file }}
# Disable auditwheel as it isn't compatible with setuptools_dso approach
# https://github.com/mdavidsaver/setuptools_dso/issues/17
CIBW_REPAIR_WHEEL_COMMAND: ''

- name: Upload Wheel and Sdist
uses: actions/upload-artifact@v2
with:
name: dist
path: dist/softioc*

- name: Upload coverage to Codecov
Expand All @@ -91,17 +106,14 @@ jobs:
needs: [build]
runs-on: ubuntu-latest
# upload to PyPI on every tag
#if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
steps:
- uses: actions/download-artifact@v2
with:
name: dist
path: dist

- name: Display structure of downloaded files
run: ls -R

- name: Publish to PyPI
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.pypi_token }}
Expand Down
2 changes: 2 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ sphinx-rtd-theme = "*"
sphinx-multiversion = {editable = true,git = "https://github.com/dls-controls/sphinx-multiversion.git",ref = "only-arg"}
setuptools-dso = "*"
aioca = "*"
pytest-asyncio = "*"

[packages]
# All other package requirements from setup.py
Expand All @@ -20,6 +21,7 @@ epicscorelibs = "*"
# Add some other useful extras
cothread = "*"
scipy = "*"
aioca = "*"

[scripts]
# Put coverage here so we don't interfere with debugging in the IDE
Expand Down
142 changes: 84 additions & 58 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions softioc/asyncio_callback.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import asyncio
import inspect
import threading


class AsyncioCallback(threading.Thread):
def __init__(self):
super().__init__()
self.loop = asyncio.new_event_loop()

def run(self):
self.loop.run_forever()

def __call__(self, func, *args):
async def async_wrapper():
ret = func(*args)
if inspect.isawaitable(ret):
await ret
asyncio.run_coroutine_threadsafe(async_wrapper(), self.loop)
28 changes: 20 additions & 8 deletions softioc/device.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,33 @@
import os
import time
import traceback
import inspect
from ctypes import *
import numpy

import cothread

from . import alarm
from .fields import DbfCodeToNumpy, DbrToDbfCode
from .imports import dbLoadDatabase, recGblResetAlarms, db_put_field
from .device_core import DeviceSupportCore, RecordLookup


dispatcher_callback = None


def use_cothread():
thomascobb marked this conversation as resolved.
Show resolved Hide resolved
import cothread
# Create our own cothread callback queue so that our callbacks
# processing doesn't interfere with other callback processing.
global dispatcher_callback
dispatcher_callback = cothread.cothread._Callback()


def use_asyncio():
from .asyncio_callback import AsyncioCallback
global dispatcher_callback
dispatcher_callback = AsyncioCallback()
dispatcher_callback.start()
thomascobb marked this conversation as resolved.
Show resolved Hide resolved


class ProcessDeviceSupportCore(DeviceSupportCore, RecordLookup):
'''Implements canonical default processing for records with a _process
method. Processing typically either copies a locally set value into the
Expand Down Expand Up @@ -79,10 +95,6 @@ def get(self):
class ProcessDeviceSupportOut(ProcessDeviceSupportCore):
_link_ = 'OUT'

# Create our own cothread callback queue so that our callbacks processing
# doesn't interfere with other callback processing.
__Callback = cothread.cothread._Callback()

def __init__(self, name, **kargs):
on_update = kargs.pop('on_update', None)
on_update_name = kargs.pop('on_update_name', None)
Expand Down Expand Up @@ -133,7 +145,7 @@ def _process(self, record):

self._value = value
if self.__on_update and self.__enable_write:
self.__Callback(self.__on_update, value)
dispatcher_callback(self.__on_update, value)
return 0


Expand Down
Loading