p4pillon 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. p4pillon-0.1.0/.github/workflows/build.yaml +137 -0
  2. p4pillon-0.1.0/.github/workflows/jekyll-gh-pages.yaml +51 -0
  3. p4pillon-0.1.0/.gitignore +227 -0
  4. p4pillon-0.1.0/.vscode/settings.json +11 -0
  5. p4pillon-0.1.0/LICENSE +28 -0
  6. p4pillon-0.1.0/PKG-INFO +98 -0
  7. p4pillon-0.1.0/README.md +70 -0
  8. p4pillon-0.1.0/_version.py +34 -0
  9. p4pillon-0.1.0/examples/asyncio/pvrecipe.py +64 -0
  10. p4pillon-0.1.0/examples/thread/hwinterface.py +122 -0
  11. p4pillon-0.1.0/examples/thread/mailbox_sharedntenum.py +21 -0
  12. p4pillon-0.1.0/examples/thread/mailbox_sharedntscalar.py +21 -0
  13. p4pillon-0.1.0/examples/thread/pvrecipe.py +27 -0
  14. p4pillon-0.1.0/p4pillon/__init__.py +0 -0
  15. p4pillon-0.1.0/p4pillon/asyncio/__init__.py +0 -0
  16. p4pillon-0.1.0/p4pillon/asyncio/pvrecipe.py +74 -0
  17. p4pillon-0.1.0/p4pillon/composite_handler.py +99 -0
  18. p4pillon-0.1.0/p4pillon/definitions.py +53 -0
  19. p4pillon-0.1.0/p4pillon/nt/__init__.py +10 -0
  20. p4pillon-0.1.0/p4pillon/nt/enum.py +50 -0
  21. p4pillon-0.1.0/p4pillon/nthandlers.py +202 -0
  22. p4pillon-0.1.0/p4pillon/pvrecipe.py +330 -0
  23. p4pillon-0.1.0/p4pillon/rules.py +709 -0
  24. p4pillon-0.1.0/p4pillon/server/__init__.py +0 -0
  25. p4pillon-0.1.0/p4pillon/server/asyncio.py +24 -0
  26. p4pillon-0.1.0/p4pillon/server/raw.py +228 -0
  27. p4pillon-0.1.0/p4pillon/server/simpleserver.py +51 -0
  28. p4pillon-0.1.0/p4pillon/server/thread.py +24 -0
  29. p4pillon-0.1.0/p4pillon/thread/__init__.py +0 -0
  30. p4pillon-0.1.0/p4pillon/thread/config_reader.py +140 -0
  31. p4pillon-0.1.0/p4pillon/thread/pvrecipe.py +67 -0
  32. p4pillon-0.1.0/p4pillon/thread/server.py +108 -0
  33. p4pillon-0.1.0/p4pillon/thread/sharednt.py +170 -0
  34. p4pillon-0.1.0/p4pillon/utils.py +74 -0
  35. p4pillon-0.1.0/pyproject.toml +90 -0
  36. p4pillon-0.1.0/tests/integration/ntenum_config.yml +29 -0
  37. p4pillon-0.1.0/tests/integration/ntscalar_config.yml +88 -0
  38. p4pillon-0.1.0/tests/integration/thread/assertions.py +123 -0
  39. p4pillon-0.1.0/tests/integration/thread/conftest.py +79 -0
  40. p4pillon-0.1.0/tests/integration/thread/helpers.py +108 -0
  41. p4pillon-0.1.0/tests/integration/thread/test_ntenum.py +82 -0
  42. p4pillon-0.1.0/tests/integration/thread/test_ntscalar.py +433 -0
  43. p4pillon-0.1.0/tests/unit/conftest.py +33 -0
  44. p4pillon-0.1.0/tests/unit/server/test_sharedpv_asyncio.py +53 -0
  45. p4pillon-0.1.0/tests/unit/server/test_sharedpv_thread.py +53 -0
  46. p4pillon-0.1.0/tests/unit/test_composite_handler.py +163 -0
  47. p4pillon-0.1.0/tests/unit/test_rules.py +506 -0
  48. p4pillon-0.1.0/tests/unit/test_utils.py +7 -0
  49. p4pillon-0.1.0/tests/unit/thread/test_config_reader.py +78 -0
  50. p4pillon-0.1.0/tests/unit/thread/test_pvrecipe.py +400 -0
  51. p4pillon-0.1.0/tests/unit/thread/test_servers.py +122 -0
  52. p4pillon-0.1.0/tests/unit/thread/test_sharednt.py +98 -0
  53. p4pillon-0.1.0/uv.lock +1028 -0
@@ -0,0 +1,137 @@
1
+ name: p4pillon
2
+
3
+ on:
4
+ push:
5
+ branches-ignore:
6
+ - "documentation"
7
+ tags:
8
+ - '**'
9
+ pull_request:
10
+ branches-ignore:
11
+ - "documentation"
12
+ tags:
13
+ - '**'
14
+ workflow_dispatch:
15
+ # Allow manual triggering of workflow
16
+
17
+ jobs:
18
+ lint:
19
+ name: Use Ruff to perform linting, formatting, and other code quality tests
20
+ runs-on: ubuntu-latest
21
+ steps:
22
+ - uses: actions/checkout@v4
23
+ - uses: actions/setup-python@v5
24
+ with:
25
+ python-version: "3.x"
26
+ - run: pip install .[test]
27
+ - run: |
28
+ ruff check --no-fix
29
+ ruff format --diff
30
+
31
+ test:
32
+ name: Run tests on multiple Python versions
33
+ needs:
34
+ - lint
35
+ strategy:
36
+ matrix:
37
+ os: [ubuntu-latest] #, mac-latest]
38
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
39
+ runs-on: ${{ matrix.os }}
40
+ continue-on-error: true
41
+ steps:
42
+ - uses: actions/checkout@v4
43
+ - name: Set up Python ${{ matrix.python-version }}
44
+ uses: actions/setup-python@v5
45
+ with:
46
+ python-version: ${{ matrix.python-version }}
47
+ - name: Install dependencies
48
+ run: |
49
+ pip install .[test]
50
+ PIP_PATH=$(which pip)
51
+ - name: Run tests
52
+ run: |
53
+ PYTHON_PATH=$(which python)
54
+ $PYTHON_PATH -m coverage run --source=. -m pytest tests/
55
+ - name: Gather coverage statistics
56
+ if: ${{ always() }}
57
+ run: |
58
+ coverage report -m
59
+ coverage xml
60
+ - name: Upload pytest test results
61
+ if: ${{ always() }}
62
+ uses: actions/upload-artifact@v4
63
+ with:
64
+ name: coverage-results-${{ matrix.os }}-${{ matrix.python-version }}
65
+ path: coverage.xml
66
+ # Use always() to always run this step to publish test results when there are test failures
67
+
68
+
69
+ build:
70
+ name: Build distribution 📦
71
+ needs:
72
+ - test
73
+ #if: github.ref == 'refs/heads/main' # Only build dist on main
74
+ runs-on: ubuntu-latest
75
+ steps:
76
+ - uses: actions/checkout@v4
77
+ with:
78
+ fetch-depth: 0 # Needed to fetch the tags
79
+ - name: Set up Python
80
+ uses: actions/setup-python@v5
81
+ with:
82
+ python-version: "3.x"
83
+ - name: Install build tools
84
+ run: >-
85
+ pip install .[dist]
86
+ - name: Build a binary wheel and a source tarball
87
+ run: python -m build
88
+ - name: Store the distribution packages
89
+ uses: actions/upload-artifact@v4
90
+ with:
91
+ name: python-package-distributions
92
+ path: dist/
93
+
94
+ publish-to-pypi:
95
+ name: >-
96
+ Publish Python 🐍 distribution 📦 to PyPI
97
+ if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes
98
+ needs:
99
+ - build
100
+ runs-on: ubuntu-latest
101
+ environment:
102
+ name: pypi
103
+ url: https://pypi.org/p/p4pillon
104
+ permissions:
105
+ id-token: write # IMPORTANT: mandatory for trusted publishing
106
+ steps:
107
+ - name: Download all the dists
108
+ uses: actions/download-artifact@v4
109
+ with:
110
+ name: python-package-distributions
111
+ path: dist/
112
+ - name: Publish distribution 📦 to PyPI
113
+ uses: pypa/gh-action-pypi-publish@release/v1
114
+
115
+ publish-to-testpypi:
116
+ name: Publish Python 🐍 distribution 📦 to TestPyPI
117
+ needs:
118
+ - build
119
+ runs-on: ubuntu-latest
120
+
121
+ environment:
122
+ name: testpypi
123
+ url: https://test.pypi.org/p/p4pillon
124
+
125
+ permissions:
126
+ id-token: write # IMPORTANT: mandatory for trusted publishing
127
+
128
+ steps:
129
+ - name: Download all the dists
130
+ uses: actions/download-artifact@v4
131
+ with:
132
+ name: python-package-distributions
133
+ path: dist/
134
+ - name: Publish distribution 📦 to TestPyPI
135
+ uses: pypa/gh-action-pypi-publish@release/v1
136
+ with:
137
+ repository-url: https://test.pypi.org/legacy/
@@ -0,0 +1,51 @@
1
+ # Sample workflow for building and deploying a Jekyll site to GitHub Pages
2
+ name: Deploy Jekyll with GitHub Pages dependencies preinstalled
3
+
4
+ on:
5
+ # Runs on pushes targeting the default branch
6
+ push:
7
+ branches: ["documentation"]
8
+
9
+ # Allows you to run this workflow manually from the Actions tab
10
+ workflow_dispatch:
11
+
12
+ # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
13
+ permissions:
14
+ contents: read
15
+ pages: write
16
+ id-token: write
17
+
18
+ # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
19
+ # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
20
+ concurrency:
21
+ group: "pages"
22
+ cancel-in-progress: false
23
+
24
+ jobs:
25
+ # Build job
26
+ build:
27
+ runs-on: ubuntu-latest
28
+ steps:
29
+ - name: Checkout
30
+ uses: actions/checkout@v4
31
+ - name: Setup Pages
32
+ uses: actions/configure-pages@v5
33
+ - name: Build with Jekyll
34
+ uses: actions/jekyll-build-pages@v1
35
+ with:
36
+ source: ./
37
+ destination: ./_site
38
+ - name: Upload artifact
39
+ uses: actions/upload-pages-artifact@v3
40
+
41
+ # Deployment job
42
+ deploy:
43
+ environment:
44
+ name: github-pages
45
+ url: ${{ steps.deployment.outputs.page_url }}
46
+ runs-on: ubuntu-latest
47
+ needs: build
48
+ steps:
49
+ - name: Deploy to GitHub Pages
50
+ id: deployment
51
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,227 @@
1
+ # Hatch-VCS
2
+ _version.py
3
+
4
+ ### VSCode .gitignore template
5
+ # VSCode files
6
+ .vscode/
7
+ .vscode/*
8
+ !.vscode/settings.json
9
+ !.vscode/tasks.json
10
+ !.vscode/launch.json
11
+ !.vscode/extensions.json
12
+ !.vscode/*.code-snippets
13
+
14
+ # Local History for Visual Studio Code
15
+ .history/
16
+
17
+ # Built Visual Studio Code Extensions
18
+ *.vsix
19
+
20
+ ### GitHub Python .gitignore template
21
+ # Byte-compiled / optimized / DLL files
22
+ __pycache__/
23
+ *.py[codz]
24
+ *$py.class
25
+
26
+ # C extensions
27
+ *.so
28
+
29
+ # Distribution / packaging
30
+ .Python
31
+ build/
32
+ develop-eggs/
33
+ dist/
34
+ downloads/
35
+ eggs/
36
+ .eggs/
37
+ lib/
38
+ lib64/
39
+ parts/
40
+ sdist/
41
+ var/
42
+ wheels/
43
+ share/python-wheels/
44
+ *.egg-info/
45
+ .installed.cfg
46
+ *.egg
47
+ MANIFEST
48
+
49
+ # PyInstaller
50
+ # Usually these files are written by a python script from a template
51
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
52
+ *.manifest
53
+ *.spec
54
+
55
+ # Installer logs
56
+ pip-log.txt
57
+ pip-delete-this-directory.txt
58
+
59
+ # Unit test / coverage reports
60
+ htmlcov/
61
+ .tox/
62
+ .nox/
63
+ .coverage
64
+ .coverage.*
65
+ .cache
66
+ nosetests.xml
67
+ coverage.xml
68
+ *.cover
69
+ *.py.cover
70
+ .hypothesis/
71
+ .pytest_cache/
72
+ cover/
73
+
74
+ # Translations
75
+ *.mo
76
+ *.pot
77
+
78
+ # Django stuff:
79
+ *.log
80
+ local_settings.py
81
+ db.sqlite3
82
+ db.sqlite3-journal
83
+
84
+ # Flask stuff:
85
+ instance/
86
+ .webassets-cache
87
+
88
+ # Scrapy stuff:
89
+ .scrapy
90
+
91
+ # Sphinx documentation
92
+ docs/_build/
93
+
94
+ # PyBuilder
95
+ .pybuilder/
96
+ target/
97
+
98
+ # Jupyter Notebook
99
+ .ipynb_checkpoints
100
+
101
+ # IPython
102
+ profile_default/
103
+ ipython_config.py
104
+
105
+ # pyenv
106
+ # For a library or package, you might want to ignore these files since the code is
107
+ # intended to run in multiple environments; otherwise, check them in:
108
+ # .python-version
109
+
110
+ # pipenv
111
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
112
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
113
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
114
+ # install all needed dependencies.
115
+ #Pipfile.lock
116
+
117
+ # UV
118
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
119
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
120
+ # commonly ignored for libraries.
121
+ #uv.lock
122
+
123
+ # poetry
124
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
125
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
126
+ # commonly ignored for libraries.
127
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
128
+ #poetry.lock
129
+ #poetry.toml
130
+
131
+ # pdm
132
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
133
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
134
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
135
+ #pdm.lock
136
+ #pdm.toml
137
+ .pdm-python
138
+ .pdm-build/
139
+
140
+ # pixi
141
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
142
+ #pixi.lock
143
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
144
+ # in the .venv directory. It is recommended not to include this directory in version control.
145
+ .pixi
146
+
147
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
148
+ __pypackages__/
149
+
150
+ # Celery stuff
151
+ celerybeat-schedule
152
+ celerybeat.pid
153
+
154
+ # SageMath parsed files
155
+ *.sage.py
156
+
157
+ # Environments
158
+ .env
159
+ .envrc
160
+ .venv
161
+ env/
162
+ venv/
163
+ ENV/
164
+ env.bak/
165
+ venv.bak/
166
+
167
+ # Spyder project settings
168
+ .spyderproject
169
+ .spyproject
170
+
171
+ # Rope project settings
172
+ .ropeproject
173
+
174
+ # mkdocs documentation
175
+ /site
176
+
177
+ # mypy
178
+ .mypy_cache/
179
+ .dmypy.json
180
+ dmypy.json
181
+
182
+ # Pyre type checker
183
+ .pyre/
184
+
185
+ # pytype static type analyzer
186
+ .pytype/
187
+
188
+ # Cython debug symbols
189
+ cython_debug/
190
+
191
+ # PyCharm
192
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
193
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
194
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
195
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
196
+ #.idea/
197
+
198
+ # Abstra
199
+ # Abstra is an AI-powered process automation framework.
200
+ # Ignore directories containing user credentials, local state, and settings.
201
+ # Learn more at https://abstra.io/docs
202
+ .abstra/
203
+
204
+ # Visual Studio Code
205
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
206
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
207
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
208
+ # you could uncomment the following to ignore the entire vscode folder
209
+ # .vscode/
210
+
211
+ # Ruff stuff:
212
+ .ruff_cache/
213
+
214
+ # PyPI configuration file
215
+ .pypirc
216
+
217
+ # Cursor
218
+ # Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
219
+ # exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
220
+ # refer to https://docs.cursor.com/context/ignore-files
221
+ .cursorignore
222
+ .cursorindexingignore
223
+
224
+ # Marimo
225
+ marimo/_static/
226
+ marimo/_lsp/
227
+ __marimo__/
@@ -0,0 +1,11 @@
1
+ {
2
+ "python.testing.unittestArgs": [
3
+ "-v",
4
+ "-s",
5
+ "./tests",
6
+ "-p",
7
+ "test_*.py"
8
+ ],
9
+ "python.testing.pytestEnabled": false,
10
+ "python.testing.unittestEnabled": true
11
+ }
p4pillon-0.1.0/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ ©Copyright 2025 UK Research and Innovation, Science and Technology Facilities Council, ISIS Neutron and Muon Facility
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,98 @@
1
+ Metadata-Version: 2.4
2
+ Name: p4pillon
3
+ Version: 0.1.0
4
+ Summary: Add your description here
5
+ Project-URL: Repository, https://github.com/epics-base/p4p
6
+ Author-email: Ivan Finch <ivan.finch@stfc.ac.uk>, Ajit Kurup <a.kurup@imperial.ac.uk>, Kathryn Baker <k.baker@stfc.ac.uk>, Aqeel AlShafei <aqeel.alshafei@stfc.ac.uk>
7
+ Maintainer-email: Ivan Finch <ivan.finch@stfc.ac.uk>
8
+ License: BSD-3-Clause
9
+ License-File: LICENSE
10
+ Keywords: epics,p4p,pva,pvaccess
11
+ Classifier: Development Status :: 2 - Pre-Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: BSD License
15
+ Classifier: Programming Language :: Python
16
+ Classifier: Typing :: Typed
17
+ Requires-Python: >=3.10
18
+ Requires-Dist: p4p>=4.2.1
19
+ Requires-Dist: pyyaml>=6.0.2
20
+ Provides-Extra: dist
21
+ Requires-Dist: build>=1.2.2.post1; extra == 'dist'
22
+ Requires-Dist: twine>=6.1.0; extra == 'dist'
23
+ Provides-Extra: test
24
+ Requires-Dist: coverage>7.9; extra == 'test'
25
+ Requires-Dist: pytest>=8.4; extra == 'test'
26
+ Requires-Dist: ruff>=0.12; extra == 'test'
27
+ Description-Content-Type: text/markdown
28
+
29
+ # p4pillon
30
+ Extensions to the [p4p](https://epics-base.github.io/p4p/) [Server API](https://epics-base.github.io/p4p/server.html), to aid in creation and managment of pvAccess servers.
31
+
32
+ [![p4pillon](https://github.com/ISISNeutronMuon/p4pillon/actions/workflows/build.yaml/badge.svg)](https://github.com/ISISNeutronMuon/p4pillon/actions/workflows/build.yaml)
33
+
34
+ ## Installation
35
+ p4pillon may be installed via
36
+ ```console
37
+ $ pip install p4pillon
38
+ ```
39
+
40
+ ### Python Version
41
+ Requires Python 3.10 or later. These extensions make extensive use of [typing](https://docs.python.org/3/library/typing.html) and other recent Python features.
42
+
43
+ ## Documentation
44
+ Documentation intended for developers using the library is available [here](https://isisneutronmuon.github.io/p4pillon/).
45
+
46
+ ### Extensions
47
+ A brief overview of the components of the library.
48
+
49
+ #### NT Logic
50
+ > [!CAUTION]
51
+ > This is not an alternative to the Process Database implemented in a traditional EPICS IOC. Although the Normative Type logic is implemented, it does not implement locking. This means that in the case of multiple simultaneous updates it is possible for a PV to become inconsistent. At this time we suggest that the NT Logic code be used for rapid prototyping and systems where consistency/reliability are not critical.
52
+
53
+ The `SharedNT` class, derived from p4p's `SharedPV` class, automatically implements the logic of Normative Types (at this time NTScalars and NTScalarArrays) using handlers. It is possible, with the `CompositeHandler` class to override this behaviour, including diabling or replacing Normative Type logic.
54
+
55
+ #### CompositeHandler and Rules
56
+ p4p only allows a single `Handler` class to be associated with a `SharedPV`. To make it easier to combine or share handlers from multiple sources a `CompositeHandler` class is provided. The supplied `CompositeHandler` is derived from the p4p `Handler`. It also derives from an OrderedDict to store componenent `Handler`s (also standard p4p `Handler`s). The `CompositeHandler` calls component handlers in the specified order, and allows the component `Handler`s to be accessed through the OrderedDict interface.
57
+
58
+ > [!NOTE]
59
+ > `CompositeHandler` is designed to work with the `Handler` class, and is **not** designed to work with the `Handler` decorators.
60
+
61
+ `Rule`s are component `Handler`s used with the `CompositeHandler` used to implement the NT Logic discussed above. The `Rule` class is derived from the `Handler` class but implements a commonly encountered flow from `put()` (for identification and authorisation), to `put()` (for operations that require comparison between the current state of the PV and its possible future state), and `open()` (for operations that only need consider the possible future state of the PV).
62
+
63
+ #### PVRecipe and Server
64
+ `PVRecipe` is a factory method used to simplify creation of `SharedNT` objects, i.e. PVs that implement Normative Type logic. It may be used in conjunction with the p4pillon `Server` class to simplify management of event loops and PV lifecycle.
65
+
66
+ ####
67
+ The `config_reader` parses a YAML file in order to construct `SharedNT` PVs which are managed by the p4pillon `Server`. This is the simplest way to create and configure
68
+
69
+ ## Testing
70
+ Install the extra dependencies required for testing using `pip install .[test]` or similar.
71
+
72
+ To run tests invoke [pytest](https://docs.pytest.org/en/latest/):
73
+
74
+ ```console
75
+ $ python -m pytest tests
76
+ ```
77
+ or to run all tests and output a coverage report:
78
+ ```
79
+ $ uv run --extra=test python -m coverage run --source=. -m pytest -x tests
80
+ $ uv run --extra=test python -m coverage report
81
+ ```
82
+
83
+ ### Linting and Formatting
84
+ This repository's CI/CD pipeling (using GitHub Actions) checks that source code meets PEP 8, and other more stringent, coding standards. This uses the [ruff](https://docs.astral.sh/ruff/) linter and code formatter. It is included in the `.[test] dependencies (see above) and may be manually invoked:
85
+
86
+ ```console
87
+ $ ruff check --fix
88
+ $ ruff format
89
+ ```
90
+
91
+ ## Releases
92
+ The release process requires use of the `.[dist]` dependencies, which may be installed with `pip install .[dist]`. A build may then be triggered with `python -m build`. Alternatively, use:
93
+
94
+ ```console
95
+ $ uv run --extra=dist python -m build
96
+ ```
97
+
98
+ Publication to either PyPi or TestPyPI is performed automatically via CI/CD (i.e. GitHub Actions) and is driven by tags. Any commit intended for package publication must be tagged with a unique tag, and the semantic version must be greater than any existing tag.
@@ -0,0 +1,70 @@
1
+ # p4pillon
2
+ Extensions to the [p4p](https://epics-base.github.io/p4p/) [Server API](https://epics-base.github.io/p4p/server.html), to aid in creation and managment of pvAccess servers.
3
+
4
+ [![p4pillon](https://github.com/ISISNeutronMuon/p4pillon/actions/workflows/build.yaml/badge.svg)](https://github.com/ISISNeutronMuon/p4pillon/actions/workflows/build.yaml)
5
+
6
+ ## Installation
7
+ p4pillon may be installed via
8
+ ```console
9
+ $ pip install p4pillon
10
+ ```
11
+
12
+ ### Python Version
13
+ Requires Python 3.10 or later. These extensions make extensive use of [typing](https://docs.python.org/3/library/typing.html) and other recent Python features.
14
+
15
+ ## Documentation
16
+ Documentation intended for developers using the library is available [here](https://isisneutronmuon.github.io/p4pillon/).
17
+
18
+ ### Extensions
19
+ A brief overview of the components of the library.
20
+
21
+ #### NT Logic
22
+ > [!CAUTION]
23
+ > This is not an alternative to the Process Database implemented in a traditional EPICS IOC. Although the Normative Type logic is implemented, it does not implement locking. This means that in the case of multiple simultaneous updates it is possible for a PV to become inconsistent. At this time we suggest that the NT Logic code be used for rapid prototyping and systems where consistency/reliability are not critical.
24
+
25
+ The `SharedNT` class, derived from p4p's `SharedPV` class, automatically implements the logic of Normative Types (at this time NTScalars and NTScalarArrays) using handlers. It is possible, with the `CompositeHandler` class to override this behaviour, including diabling or replacing Normative Type logic.
26
+
27
+ #### CompositeHandler and Rules
28
+ p4p only allows a single `Handler` class to be associated with a `SharedPV`. To make it easier to combine or share handlers from multiple sources a `CompositeHandler` class is provided. The supplied `CompositeHandler` is derived from the p4p `Handler`. It also derives from an OrderedDict to store componenent `Handler`s (also standard p4p `Handler`s). The `CompositeHandler` calls component handlers in the specified order, and allows the component `Handler`s to be accessed through the OrderedDict interface.
29
+
30
+ > [!NOTE]
31
+ > `CompositeHandler` is designed to work with the `Handler` class, and is **not** designed to work with the `Handler` decorators.
32
+
33
+ `Rule`s are component `Handler`s used with the `CompositeHandler` used to implement the NT Logic discussed above. The `Rule` class is derived from the `Handler` class but implements a commonly encountered flow from `put()` (for identification and authorisation), to `put()` (for operations that require comparison between the current state of the PV and its possible future state), and `open()` (for operations that only need consider the possible future state of the PV).
34
+
35
+ #### PVRecipe and Server
36
+ `PVRecipe` is a factory method used to simplify creation of `SharedNT` objects, i.e. PVs that implement Normative Type logic. It may be used in conjunction with the p4pillon `Server` class to simplify management of event loops and PV lifecycle.
37
+
38
+ ####
39
+ The `config_reader` parses a YAML file in order to construct `SharedNT` PVs which are managed by the p4pillon `Server`. This is the simplest way to create and configure
40
+
41
+ ## Testing
42
+ Install the extra dependencies required for testing using `pip install .[test]` or similar.
43
+
44
+ To run tests invoke [pytest](https://docs.pytest.org/en/latest/):
45
+
46
+ ```console
47
+ $ python -m pytest tests
48
+ ```
49
+ or to run all tests and output a coverage report:
50
+ ```
51
+ $ uv run --extra=test python -m coverage run --source=. -m pytest -x tests
52
+ $ uv run --extra=test python -m coverage report
53
+ ```
54
+
55
+ ### Linting and Formatting
56
+ This repository's CI/CD pipeling (using GitHub Actions) checks that source code meets PEP 8, and other more stringent, coding standards. This uses the [ruff](https://docs.astral.sh/ruff/) linter and code formatter. It is included in the `.[test] dependencies (see above) and may be manually invoked:
57
+
58
+ ```console
59
+ $ ruff check --fix
60
+ $ ruff format
61
+ ```
62
+
63
+ ## Releases
64
+ The release process requires use of the `.[dist]` dependencies, which may be installed with `pip install .[dist]`. A build may then be triggered with `python -m build`. Alternatively, use:
65
+
66
+ ```console
67
+ $ uv run --extra=dist python -m build
68
+ ```
69
+
70
+ Publication to either PyPi or TestPyPI is performed automatically via CI/CD (i.e. GitHub Actions) and is driven by tags. Any commit intended for package publication must be tagged with a unique tag, and the semantic version must be greater than any existing tag.
@@ -0,0 +1,34 @@
1
+ # file generated by setuptools-scm
2
+ # don't change, don't track in version control
3
+
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
12
+
13
+ TYPE_CHECKING = False
14
+ if TYPE_CHECKING:
15
+ from typing import Tuple
16
+ from typing import Union
17
+
18
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
20
+ else:
21
+ VERSION_TUPLE = object
22
+ COMMIT_ID = object
23
+
24
+ version: str
25
+ __version__: str
26
+ __version_tuple__: VERSION_TUPLE
27
+ version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
30
+
31
+ __version__ = version = '0.1.0'
32
+ __version_tuple__ = version_tuple = (0, 1, 0)
33
+
34
+ __commit_id__ = commit_id = None