diff --git a/.github/workflows/_test.yml b/.github/workflows/_test.yml
index 9ba36e4..65c8cfa 100644
--- a/.github/workflows/_test.yml
+++ b/.github/workflows/_test.yml
@@ -33,6 +33,8 @@ jobs:
- name: Install uv
uses: astral-sh/setup-uv@v7
+ - name: List packages
+ run: uv run --locked uv pip freeze
- name: Run tests
run: uv run --locked tox -e tests
diff --git a/example-synoptic/b23-services/config/devsta.db b/example-synoptic/b23-services/config/devsta.db
new file mode 100644
index 0000000..cc907c7
--- /dev/null
+++ b/example-synoptic/b23-services/config/devsta.db
@@ -0,0 +1,22 @@
+###################################################
+## THIS FILE HAS BEEN AUTOGENERATED; DO NOT EDIT ##
+###################################################
+
+record(calc, "BL23B-OP-MR-03:DEVSTA")
+{
+ field(ACKT, "NO")
+ field(CALC, "(A|B|C|D|E|F|G|H|I|J|K|L)>0?1:0")
+ field(INPA, "BL23B-OP-MR-03:MP:BUSY NPP NMS")
+ field(INPB, "BL23B-OP-MR-03:MP:DMOV.SEVR NPP MS")
+ field(INPC, "BL23B-OP-MR-03:MP:SELECT.SEVR NPP MS")
+ field(INPD, "BL23B-OP-MR-03:PITCH.MOVN NPP MS")
+ field(INPE, "BL23B-OP-MR-03:YAW.MOVN NPP MS")
+ field(INPF, "")
+ field(INPG, "")
+ field(INPH, "")
+ field(INPI, "")
+ field(INPJ, "")
+ field(INPK, "")
+ field(INPL, "")
+ field(SCAN, "1 second")
+}
diff --git a/example-synoptic/b23-services/synoptic/IMG1.bob b/example-synoptic/b23-services/synoptic/IMG1.bob
index ba36062..65b3372 100644
--- a/example-synoptic/b23-services/synoptic/IMG1.bob
+++ b/example-synoptic/b23-services/synoptic/IMG1.bob
@@ -8,12 +8,13 @@
351
432
- mks937a.mks937aImg
+ BL23B-VA-IMG-01
301
382
techui-support/bob/mks937a/mks937aImg.bob
BL23B-VA-IMG-01
+ https://b23-opis.diamond.ac.uk/bl23b-va-img-01
0
0
diff --git a/example-synoptic/b23-services/synoptic/IMG11.bob b/example-synoptic/b23-services/synoptic/IMG11.bob
index c7a5d42..e29f6eb 100644
--- a/example-synoptic/b23-services/synoptic/IMG11.bob
+++ b/example-synoptic/b23-services/synoptic/IMG11.bob
@@ -8,12 +8,13 @@
351
432
- mks937a.mks937aImg
+ BL23B-VA-IMG-11
301
382
techui-support/bob/mks937a/mks937aImg.bob
BL23B-VA-IMG-11
+ https://b23-opis.diamond.ac.uk/bl23b-va-img-11
0
0
diff --git a/example-synoptic/b23-services/synoptic/IMG12.bob b/example-synoptic/b23-services/synoptic/IMG12.bob
index 2ac84dd..c078d23 100644
--- a/example-synoptic/b23-services/synoptic/IMG12.bob
+++ b/example-synoptic/b23-services/synoptic/IMG12.bob
@@ -8,12 +8,13 @@
351
432
- mks937a.mks937aImg
+ BL23B-VA-IMG-12
301
382
techui-support/bob/mks937a/mks937aImg.bob
BL23B-VA-IMG-12
+ https://b23-opis.diamond.ac.uk/bl23b-va-img-12
0
0
diff --git a/example-synoptic/b23-services/synoptic/IONP1.bob b/example-synoptic/b23-services/synoptic/IONP1.bob
index 8f547f4..1495f48 100644
--- a/example-synoptic/b23-services/synoptic/IONP1.bob
+++ b/example-synoptic/b23-services/synoptic/IONP1.bob
@@ -8,12 +8,13 @@
351
293
- digitelMpc.digitelMpcIonp
+ BL23B-VA-IONP-01
301
243
techui-support/bob/digitelMpc/digitelMpcIonp.bob
BL23B-VA-IONP-01
+ https://b23-opis.diamond.ac.uk/bl23b-va-ionp-01
0
0
diff --git a/example-synoptic/b23-services/synoptic/IONP11.bob b/example-synoptic/b23-services/synoptic/IONP11.bob
index a77ee59..ca4dc00 100644
--- a/example-synoptic/b23-services/synoptic/IONP11.bob
+++ b/example-synoptic/b23-services/synoptic/IONP11.bob
@@ -8,12 +8,13 @@
351
293
- digitelMpc.digitelMpcIonp
+ BL23B-VA-IONP-11
301
243
techui-support/bob/digitelMpc/digitelMpcIonp.bob
BL23B-VA-IONP-11
+ https://b23-opis.diamond.ac.uk/bl23b-va-ionp-11
0
0
diff --git a/example-synoptic/b23-services/synoptic/IONP12.bob b/example-synoptic/b23-services/synoptic/IONP12.bob
index ac88312..de2f2b8 100644
--- a/example-synoptic/b23-services/synoptic/IONP12.bob
+++ b/example-synoptic/b23-services/synoptic/IONP12.bob
@@ -8,12 +8,13 @@
351
293
- digitelMpc.digitelMpcIonp
+ BL23B-VA-IONP-12
301
243
techui-support/bob/digitelMpc/digitelMpcIonp.bob
BL23B-VA-IONP-12
+ https://b23-opis.diamond.ac.uk/bl23b-va-ionp-12
0
0
diff --git a/example-synoptic/b23-services/synoptic/IONP21.bob b/example-synoptic/b23-services/synoptic/IONP21.bob
index 2a24aac..75a645e 100644
--- a/example-synoptic/b23-services/synoptic/IONP21.bob
+++ b/example-synoptic/b23-services/synoptic/IONP21.bob
@@ -8,12 +8,13 @@
351
293
- digitelMpc.digitelMpcIonp
+ BL23B-VA-IONP-21
301
243
techui-support/bob/digitelMpc/digitelMpcIonp.bob
BL23B-VA-IONP-21
+ https://b23-opis.diamond.ac.uk/bl23b-va-ionp-21
0
0
diff --git a/example-synoptic/b23-services/synoptic/JsonMap.json b/example-synoptic/b23-services/synoptic/JsonMap.json
index 2a7a88b..aaa7642 100644
--- a/example-synoptic/b23-services/synoptic/JsonMap.json
+++ b/example-synoptic/b23-services/synoptic/JsonMap.json
@@ -317,76 +317,6 @@
"name": "PIRG2"
}
},
- {
- "file": "MOD2.bob",
- "children": [
- {
- "file": "techui-support/bob/ADAravis/ADAravis_detail.bob",
- "macros": {
- "P": "BL23B-DI-MOD-02",
- "R": ":CAM:"
- }
- },
- {
- "file": "techui-support/bob/ADAravis/NDPluginROI.pvi.bob",
- "macros": {
- "P": "BL23B-DI-MOD-02",
- "R": ":ROI:"
- }
- },
- {
- "file": "techui-support/bob/ADAravis/NDPluginStats.pvi.bob",
- "macros": {
- "P": "BL23B-DI-MOD-02",
- "R": ":STAT:"
- }
- },
- {
- "file": "techui-support/bob/ADAravis/NDFileHDF5.pvi.bob",
- "macros": {
- "P": "BL23B-DI-MOD-02",
- "R": ":HDF5:"
- }
- }
- ]
- },
- {
- "file": "MOD1.bob",
- "children": [
- {
- "file": "techui-support/bob/ADAravis/ADAravis_detail.bob",
- "duplicate": true,
- "macros": {
- "P": "BL23B-DI-MOD-01",
- "R": ":CAM:"
- }
- },
- {
- "file": "techui-support/bob/ADAravis/NDPluginROI.pvi.bob",
- "duplicate": true,
- "macros": {
- "P": "BL23B-DI-MOD-01",
- "R": ":ROI:"
- }
- },
- {
- "file": "techui-support/bob/ADAravis/NDPluginStats.pvi.bob",
- "duplicate": true,
- "macros": {
- "P": "BL23B-DI-MOD-01",
- "R": ":STAT:"
- }
- },
- {
- "file": "techui-support/bob/ADAravis/NDFileHDF5.pvi.bob",
- "duplicate": true,
- "macros": {
- "P": "BL23B-DI-MOD-01",
- "R": ":HDF5:"
- }
- }
- ]
- },
{
"file": "IMG11.bob",
"macros": {
@@ -501,11 +431,73 @@
},
{
"file": "MOD1.bob",
- "duplicate": true
+ "children": [
+ {
+ "file": "techui-support/bob/ADAravis/ADAravis_detail.bob",
+ "macros": {
+ "P": "BL23B-DI-MOD-01",
+ "R": ":CAM:"
+ }
+ },
+ {
+ "file": "techui-support/bob/ADAravis/NDPluginROI.pvi.bob",
+ "macros": {
+ "P": "BL23B-DI-MOD-01",
+ "R": ":ROI:"
+ }
+ },
+ {
+ "file": "techui-support/bob/ADAravis/NDPluginStats.pvi.bob",
+ "macros": {
+ "P": "BL23B-DI-MOD-01",
+ "R": ":STAT:"
+ }
+ },
+ {
+ "file": "techui-support/bob/ADAravis/NDFileHDF5.pvi.bob",
+ "macros": {
+ "P": "BL23B-DI-MOD-01",
+ "R": ":HDF5:"
+ }
+ }
+ ]
},
{
"file": "MOD2.bob",
- "duplicate": true
+ "children": [
+ {
+ "file": "techui-support/bob/ADAravis/ADAravis_detail.bob",
+ "duplicate": true,
+ "macros": {
+ "P": "BL23B-DI-MOD-02",
+ "R": ":CAM:"
+ }
+ },
+ {
+ "file": "techui-support/bob/ADAravis/NDPluginROI.pvi.bob",
+ "duplicate": true,
+ "macros": {
+ "P": "BL23B-DI-MOD-02",
+ "R": ":ROI:"
+ }
+ },
+ {
+ "file": "techui-support/bob/ADAravis/NDPluginStats.pvi.bob",
+ "duplicate": true,
+ "macros": {
+ "P": "BL23B-DI-MOD-02",
+ "R": ":STAT:"
+ }
+ },
+ {
+ "file": "techui-support/bob/ADAravis/NDFileHDF5.pvi.bob",
+ "duplicate": true,
+ "macros": {
+ "P": "BL23B-DI-MOD-02",
+ "R": ":HDF5:"
+ }
+ }
+ ]
}
]
}
diff --git a/example-synoptic/b23-services/synoptic/M3.bob b/example-synoptic/b23-services/synoptic/M3.bob
index 7a83e8c..c1e1dce 100644
--- a/example-synoptic/b23-services/synoptic/M3.bob
+++ b/example-synoptic/b23-services/synoptic/M3.bob
@@ -8,47 +8,50 @@
255
540
- :Y
+ Y
205
120
techui-support/bob/pmac/motor_embed.bob
BL23B-OP-MR-03
- :Y
+ Y
+ https://b23-opis.diamond.ac.uk/bl23b-op-mr-03
0
0
- :YAW
+ YAW
205
120
techui-support/bob/pmac/motor_embed.bob
BL23B-OP-MR-03
- :YAW
+ YAW
+ https://b23-opis.diamond.ac.uk/bl23b-op-mr-03
0
150
- :PITCH
+ PITCH
205
120
techui-support/bob/pmac/motor_embed.bob
BL23B-OP-MR-03
- :PITCH
+ PITCH
+ https://b23-opis.diamond.ac.uk/bl23b-op-mr-03
0
300
- pmac.GeoBrick
+ BL23B-MO-PMAC-01
100
40
- BL23B-MO-PMAC-01
- pmac.GeoBrick
+
+ BL23B-MO-PMAC-01
Open Display
diff --git a/example-synoptic/b23-services/synoptic/MOD1.bob b/example-synoptic/b23-services/synoptic/MOD1.bob
index 12a3934..069c384 100644
--- a/example-synoptic/b23-services/synoptic/MOD1.bob
+++ b/example-synoptic/b23-services/synoptic/MOD1.bob
@@ -5,26 +5,27 @@
MOD1
0
0
- 1040
- 690
+ 910
+ 570
- :CAM:
- 990
- 570
+ CAM
+ 860
+ 450
techui-support/bob/ADAravis/ADAravis_summary.bob
BL23B-DI-MOD-01
- :CAM:
+ CAM
+ https://b23-opis.diamond.ac.uk/bl23b-di-mod-01
0
0
- :CAM:
+ CAM
100
40
- BL23B-DI-MOD-01:CAM:
- :CAM:
+
+ CAM
Open Display
@@ -37,14 +38,14 @@
0
- 600
+ 480
- :ROI:
+ ROI
100
40
- BL23B-DI-MOD-01:ROI:
- :ROI:
+
+ ROI
Open Display
@@ -57,14 +58,14 @@
120
- 600
+ 480
- :STAT:
+ STAT
100
40
- BL23B-DI-MOD-01:STAT:
- :STAT:
+
+ STAT
Open Display
@@ -77,14 +78,14 @@
240
- 600
+ 480
- :HDF5:
+ HDF5
100
40
- BL23B-DI-MOD-01:HDF5:
- :HDF5:
+
+ HDF5
Open Display
@@ -97,7 +98,7 @@
360
- 600
+ 480
diff --git a/example-synoptic/b23-services/synoptic/MOD2.bob b/example-synoptic/b23-services/synoptic/MOD2.bob
index 6d9e02a..6b1c798 100644
--- a/example-synoptic/b23-services/synoptic/MOD2.bob
+++ b/example-synoptic/b23-services/synoptic/MOD2.bob
@@ -5,26 +5,27 @@
MOD2
0
0
- 1040
- 690
+ 910
+ 570
- :CAM:
- 990
- 570
+ CAM
+ 860
+ 450
techui-support/bob/ADAravis/ADAravis_summary.bob
BL23B-DI-MOD-02
- :CAM:
+ CAM
+ https://b23-opis.diamond.ac.uk/bl23b-di-mod-02
0
0
- :CAM:
+ CAM
100
40
- BL23B-DI-MOD-02:CAM:
- :CAM:
+
+ CAM
Open Display
@@ -37,14 +38,14 @@
0
- 600
+ 480
- :ROI:
+ ROI
100
40
- BL23B-DI-MOD-02:ROI:
- :ROI:
+
+ ROI
Open Display
@@ -57,14 +58,14 @@
120
- 600
+ 480
- :STAT:
+ STAT
100
40
- BL23B-DI-MOD-02:STAT:
- :STAT:
+
+ STAT
Open Display
@@ -77,14 +78,14 @@
240
- 600
+ 480
- :HDF5:
+ HDF5
100
40
- BL23B-DI-MOD-02:HDF5:
- :HDF5:
+
+ HDF5
Open Display
@@ -97,7 +98,7 @@
360
- 600
+ 480
diff --git a/example-synoptic/b23-services/synoptic/PIRG1.bob b/example-synoptic/b23-services/synoptic/PIRG1.bob
index eb79980..548bf04 100644
--- a/example-synoptic/b23-services/synoptic/PIRG1.bob
+++ b/example-synoptic/b23-services/synoptic/PIRG1.bob
@@ -8,12 +8,13 @@
351
406
- mks937a.mks937aPirg
+ BL23B-VA-PIRG-01
301
356
techui-support/bob/mks937a/mks937aPirg.bob
BL23B-VA-PIRG-01
+ https://b23-opis.diamond.ac.uk/bl23b-va-pirg-01
0
0
diff --git a/example-synoptic/b23-services/synoptic/PIRG11.bob b/example-synoptic/b23-services/synoptic/PIRG11.bob
index 25ab0a2..0d8a5d1 100644
--- a/example-synoptic/b23-services/synoptic/PIRG11.bob
+++ b/example-synoptic/b23-services/synoptic/PIRG11.bob
@@ -8,12 +8,13 @@
351
406
- mks937a.mks937aPirg
+ BL23B-VA-PIRG-11
301
356
techui-support/bob/mks937a/mks937aPirg.bob
BL23B-VA-PIRG-11
+ https://b23-opis.diamond.ac.uk/bl23b-va-pirg-11
0
0
diff --git a/example-synoptic/b23-services/synoptic/PIRG12.bob b/example-synoptic/b23-services/synoptic/PIRG12.bob
index fb8765d..b99119c 100644
--- a/example-synoptic/b23-services/synoptic/PIRG12.bob
+++ b/example-synoptic/b23-services/synoptic/PIRG12.bob
@@ -8,12 +8,13 @@
351
406
- mks937a.mks937aPirg
+ BL23B-VA-PIRG-12
301
356
techui-support/bob/mks937a/mks937aPirg.bob
BL23B-VA-PIRG-12
+ https://b23-opis.diamond.ac.uk/bl23b-va-pirg-12
0
0
diff --git a/example-synoptic/b23-services/synoptic/SPACE11.bob b/example-synoptic/b23-services/synoptic/SPACE11.bob
index d195aec..2eddfb5 100644
--- a/example-synoptic/b23-services/synoptic/SPACE11.bob
+++ b/example-synoptic/b23-services/synoptic/SPACE11.bob
@@ -8,67 +8,73 @@
1013
844
- mks937a.mks937aImg
+ BL23B-VA-IMG-11
301
382
techui-support/bob/mks937a/mks937aImg.bob
BL23B-VA-IMG-11
+ https://b23-opis.diamond.ac.uk/bl23b-va-img-11
0
0
- mks937a.mks937aImg
+ BL23B-VA-IMG-12
301
382
techui-support/bob/mks937a/mks937aImg.bob
BL23B-VA-IMG-12
+ https://b23-opis.diamond.ac.uk/bl23b-va-img-12
0
412
- mks937a.mks937aPirg
+ BL23B-VA-PIRG-11
301
356
techui-support/bob/mks937a/mks937aPirg.bob
BL23B-VA-PIRG-11
+ https://b23-opis.diamond.ac.uk/bl23b-va-pirg-11
331
0
- mks937a.mks937aPirg
+ BL23B-VA-PIRG-12
301
356
techui-support/bob/mks937a/mks937aPirg.bob
BL23B-VA-PIRG-12
+ https://b23-opis.diamond.ac.uk/bl23b-va-pirg-12
331
386
- digitelMpc.digitelMpcIonp
+ BL23B-VA-IONP-11
301
243
techui-support/bob/digitelMpc/digitelMpcIonp.bob
BL23B-VA-IONP-11
+ https://b23-opis.diamond.ac.uk/bl23b-va-ionp-11
662
0
- digitelMpc.digitelMpcIonp
+ BL23B-VA-IONP-12
301
243
techui-support/bob/digitelMpc/digitelMpcIonp.bob
BL23B-VA-IONP-12
+ https://b23-opis.diamond.ac.uk/bl23b-va-ionp-12
662
273
diff --git a/example-synoptic/b23-services/synoptic/techui.yaml b/example-synoptic/b23-services/synoptic/techui.yaml
index 26ef7b1..24eaec3 100644
--- a/example-synoptic/b23-services/synoptic/techui.yaml
+++ b/example-synoptic/b23-services/synoptic/techui.yaml
@@ -3,6 +3,7 @@ beamline:
short_dom: B23
long_dom: BL23B
desc: B23 Beamline
+ url: b23-opis.diamond.ac.uk
components:
# ----- VACUUM -----
@@ -139,6 +140,12 @@ components:
prefix: BL23B-OP-MR-03
extras:
- BL23B-MO-PMAC-01
+ devsta:
+ - BL23B-OP-MR-03:MP:BUSY NPP NMS
+ - BL23B-OP-MR-03:MP:DMOV.SEVR NPP MS
+ - BL23B-OP-MR-03:MP:SELECT.SEVR NPP MS
+ - BL23B-OP-MR-03:PITCH.MOVN NPP MS
+ - BL23B-OP-MR-03:YAW.MOVN NPP MS
# ----- MOD -----
diff --git a/pyproject.toml b/pyproject.toml
index 0501d3f..eb719b3 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -27,6 +27,8 @@ dependencies = [
"typer>=0.16.0",
"rich>=14.1.0",
"pydantic>=2.11.7",
+ "softioc>=4.6.1",
+ "epicsdbbuilder>=1.5",
]
scripts = { techui-builder = "techui_builder.__main__:app" }
diff --git a/src/techui_builder/__main__.py b/src/techui_builder/__main__.py
index 2867e1e..9ed744b 100644
--- a/src/techui_builder/__main__.py
+++ b/src/techui_builder/__main__.py
@@ -156,6 +156,7 @@ def main(
gui.setup()
gui.create_screens()
+ gui.write_devsta_pvs()
logger_.info(f"Screens generated for {gui.conf.beamline.short_dom}.")
diff --git a/src/techui_builder/builder.py b/src/techui_builder/builder.py
index 6338f0f..4efa78d 100644
--- a/src/techui_builder/builder.py
+++ b/src/techui_builder/builder.py
@@ -7,8 +7,10 @@
from typing import Any
import yaml
+from epicsdbbuilder.recordbase import Record
from lxml import etree, objectify
from lxml.objectify import ObjectifiedElement
+from softioc.builder import records
from techui_builder.generate import Generator
from techui_builder.models import Entity, TechUi
@@ -45,6 +47,7 @@ class Builder:
entities: defaultdict[str, list[Entity]] = field(
default_factory=lambda: defaultdict(list), init=False
)
+ devsta_pvs: dict[str, Record] = field(default_factory=dict, init=False)
_services_dir: Path = field(init=False, repr=False)
_gui_map: dict = field(init=False, repr=False)
_write_directory: Path = field(default=Path("opis"), init=False, repr=False)
@@ -96,6 +99,54 @@ def clean_files(self):
logger_.debug(f"Removing generated file: {file_.name}")
os.remove(file_)
+ def _create_devsta_pv(self, prefix: str, inputs: list[str]):
+ # Extract all input PVs, provided a default "" if not provided
+ values = [(inputs[i] if i < len(inputs) else "") for i in range(12)]
+ inpa, inpb, inpc, inpd, inpe, inpf, inpg, inph, inpi, inpj, inpk, inpl = values
+
+ devsta_pv = records.calc( # pyright: ignore[reportAttributeAccessIssue]
+ f"{prefix}:DEVSTA",
+ CALC="(A|B|C|D|E|F|G|H|I|J|K|L)>0?1:0",
+ SCAN="1 second",
+ ACKT="NO",
+ INPA=inpa,
+ INPB=inpb,
+ INPC=inpc,
+ INPD=inpd,
+ INPE=inpe,
+ INPF=inpf,
+ INPG=inpg,
+ INPH=inph,
+ INPI=inpi,
+ INPJ=inpj,
+ INPK=inpk,
+ INPL=inpl,
+ )
+
+ self.devsta_pvs[prefix] = devsta_pv
+
+ def write_devsta_pvs(self):
+ conf_dir = self._write_directory.parent.joinpath("config")
+
+ # Create the config/ dir if it doesn't exist
+ if not conf_dir.exists():
+ os.mkdir(conf_dir)
+
+ with open(conf_dir.joinpath("devsta.db"), "w") as f:
+ # Add a header explaining the file is autogenerated
+ f.write("#" * 51 + "\n")
+ f.write(
+ "#" * 2
+ + " THIS FILE HAS BEEN AUTOGENERATED; DO NOT EDIT "
+ + "#" * 2
+ + "\n"
+ )
+ f.write("#" * 51 + "\n")
+
+ # Write the devsta PVs
+ for dpv in self.devsta_pvs.values():
+ dpv.Print(f)
+
def _extract_services(self):
"""
Finds the services folders in the services directory
@@ -154,6 +205,10 @@ def create_screens(self):
# any extras defined
for component_name, component in self.conf.components.items():
screen_entities: list[Entity] = []
+
+ if component.devsta is not None:
+ self._create_devsta_pv(component.prefix, component.devsta)
+
# ONLY IF there is a matching component and entity, generate a screen
if component.prefix in self.entities.keys():
screen_entities.extend(self.entities[component.prefix])
diff --git a/src/techui_builder/models.py b/src/techui_builder/models.py
index dc1a4f5..c1ab03e 100644
--- a/src/techui_builder/models.py
+++ b/src/techui_builder/models.py
@@ -44,6 +44,11 @@
""",
re.VERBOSE,
)
+# Checks for database link flags, e.g. NPP MS, at the end
+_DATABASE_FLAGS_RE = re.compile(
+ r"(?:PP|NPP)?" + r"(?:[ ]+(?:MS|NMS|MSS|MSI))?$",
+ re.VERBOSE,
+)
_LONG_DOM_RE = re.compile(r"^[a-zA-Z]{2}\d{2}[a-zA-Z]$")
_SHORT_DOM_RE = re.compile(r"^[a-zA-Z]{1}\d{2}(-[0-9]{1})?$")
_OPIS_URL_RE = re.compile(r"^(https:\/\/)?([a-z0-9]{3}-(?:[0-9]-)?opis(?:.[a-z0-9]*)*)")
@@ -99,6 +104,7 @@ class Component(BaseModel):
desc: str | None = None
extras: list[str] | None = None
file: str | None = None
+ devsta: list[str] | None = None
model_config = ConfigDict(extra="forbid")
@field_validator("prefix")
@@ -119,6 +125,26 @@ def _check_extras(cls, v: list[str]) -> list[str]:
raise ValueError("extras must contain unique items")
return v
+ @field_validator("devsta")
+ @classmethod
+ def _check_devsta(cls, v: list[str]) -> list[str]:
+ for p in v:
+ prefix, flags = p.split(" ", 1)
+
+ if not _DLS_PREFIX_RE.match(prefix):
+ raise ValueError(
+ f"devsta item '{p}' does not match extended DLS prefix pattern"
+ )
+ if not _DATABASE_FLAGS_RE.match(flags):
+ raise ValueError(
+ f"devsta item '{p}' does have valid database link flags"
+ )
+
+ # ensure unique (schema enforces too)
+ if len(set(v)) != len(v):
+ raise ValueError("devsta must contain unique items")
+ return v
+
@computed_field
@property
def P(self) -> str | None: # noqa: N802
diff --git a/tests/test_models.py b/tests/test_models.py
index e2691b0..f5c5e81 100644
--- a/tests/test_models.py
+++ b/tests/test_models.py
@@ -44,13 +44,14 @@ def test_component_object(component: Component):
assert component.P == "BL01T-EA-TEST-02"
assert component.R is None
assert component.attribute is None
+ assert component.devsta is None
def test_component_repr(component: Component):
assert (
str(component)
== "prefix='BL01T-EA-TEST-02' desc='Test Device' extras=None\
- file=None P='BL01T-EA-TEST-02' R=None attribute=None"
+ file=None devsta=None P='BL01T-EA-TEST-02' R=None attribute=None"
)
diff --git a/uv.lock b/uv.lock
index bdce553..ab44643 100644
--- a/uv.lock
+++ b/uv.lock
@@ -278,6 +278,34 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/36/41/04e2a649058b0713b00d6c9bd22da35618bb157289e05d068e51fddf8d7e/dunamai-1.25.0-py3-none-any.whl", hash = "sha256:7f9dc687dd3256e613b6cc978d9daabfd2bb5deb8adc541fc135ee423ffa98ab", size = 27022, upload-time = "2025-07-04T19:25:54.863Z" },
]
+[[package]]
+name = "epicscorelibs"
+version = "7.0.7.99.1.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+ { name = "setuptools" },
+ { name = "setuptools-dso" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/80/07/d820b96a0e8d6b99742f984788d7679d5a60000f99c2ee10094ddc4baf53/epicscorelibs-7.0.7.99.1.2.tar.gz", hash = "sha256:2a74a53b438bbbbeef13c74640a4d3060d35de78ce8989f3158148f38534cd43", size = 1630005, upload-time = "2025-07-31T08:11:59.809Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/07/eb/44475b09aef9ffc31d3b6f5028fa3cbffd1144a3a87c3a87349a2991e6d1/epicscorelibs-7.0.7.99.1.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f44f67edd96a0da13d99e9fc798c8b49c4441475cc732257a00c17923e6c5b74", size = 7768865, upload-time = "2025-07-31T08:14:18.201Z" },
+ { url = "https://files.pythonhosted.org/packages/50/54/5357954339fb1d722771dfc11a2ece67ffe8aeb8ec976be841bfe42752fa/epicscorelibs-7.0.7.99.1.2-cp312-cp312-manylinux2014_x86_64.whl", hash = "sha256:0fe1960c2db0d6480bb0389616d2803aeca6a5836d12b1857d6c4c063f7cf709", size = 5378307, upload-time = "2025-07-31T08:12:36.774Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/63/4787c4a86ba45fdfdb9905da647a9b537ae80be7e7be0084a17871212ee9/epicscorelibs-7.0.7.99.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:6949d1596362deec124fbbd09a86ee3b21caeb3ac75a7e80d59addec07bb6942", size = 2502786, upload-time = "2025-07-31T08:18:21.809Z" },
+ { url = "https://files.pythonhosted.org/packages/c2/67/2b7f4e76a102a66e48a25b3278df09b7547eed5df1cef73e9396ec49df3b/epicscorelibs-7.0.7.99.1.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4106d707c5c6a1c35155adbea03275b64fa4c77adba1e820cc8f1dbe3faf62c3", size = 7769136, upload-time = "2025-07-31T08:19:01.16Z" },
+ { url = "https://files.pythonhosted.org/packages/a2/af/6bb0e1de4fb7218fa4ba95fe91ba1fd4a5661dd28a461eff6a0f609c996c/epicscorelibs-7.0.7.99.1.2-cp313-cp313-manylinux2014_x86_64.whl", hash = "sha256:be8f328fe16b13fa9ca1dabf85c53561a3209b3c5df693c6b959351f6d11fabc", size = 5378303, upload-time = "2025-07-31T08:12:39.169Z" },
+ { url = "https://files.pythonhosted.org/packages/46/72/fef75e967d5663359739ef23310cfc37e84149bc4190aa8f95482feaa99e/epicscorelibs-7.0.7.99.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:0cd102e3f2292d10441b675e8cf7c2fcbaf4e4b0474b9d3813ed3cdeea7a1508", size = 2502677, upload-time = "2025-07-31T08:18:33.207Z" },
+]
+
+[[package]]
+name = "epicsdbbuilder"
+version = "1.5"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/cc/31/c1b5f49621934d1bcd87d306817d9d81fa5d0935476d7ba73b98181f6557/epicsdbbuilder-1.5.tar.gz", hash = "sha256:698ad5882de4a626a82086139ff95204e8de72e63d03d9f22d4418da3a6c8566", size = 19193, upload-time = "2021-12-17T14:05:58.106Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/10/f8/858c81f516cb9d1c1f73e8bf379be2cbec4388c93f48a4eb118c47f32d4d/epicsdbbuilder-1.5-py3-none-any.whl", hash = "sha256:ae8dc724c72478d2c6a68b08145d027a50af98702d17e4692f2d73f145818e74", size = 23682, upload-time = "2021-12-17T14:05:57.141Z" },
+]
+
[[package]]
name = "filelock"
version = "3.20.0"
@@ -537,6 +565,69 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/ad/b7/bc0cdbc2cc3a66fcac82c79912e135a0110b37b790a14c477f18e18d90cd/nodejs_wheel_binaries-24.11.1-py2.py3-none-win_arm64.whl", hash = "sha256:376b9ea1c4bc1207878975dfeb604f7aa5668c260c6154dcd2af9d42f7734116", size = 39026497, upload-time = "2025-11-18T18:21:54.634Z" },
]
+[[package]]
+name = "numpy"
+version = "2.3.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d0/19/95b3d357407220ed24c139018d2518fab0a61a948e68286a25f1a4d049ff/numpy-2.3.3.tar.gz", hash = "sha256:ddc7c39727ba62b80dfdbedf400d1c10ddfa8eefbd7ec8dcb118be8b56d31029", size = 20576648, upload-time = "2025-09-09T16:54:12.543Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/51/5d/bb7fc075b762c96329147799e1bcc9176ab07ca6375ea976c475482ad5b3/numpy-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cfdd09f9c84a1a934cde1eec2267f0a43a7cd44b2cca4ff95b7c0d14d144b0bf", size = 20957014, upload-time = "2025-09-09T15:56:29.966Z" },
+ { url = "https://files.pythonhosted.org/packages/6b/0e/c6211bb92af26517acd52125a237a92afe9c3124c6a68d3b9f81b62a0568/numpy-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb32e3cf0f762aee47ad1ddc6672988f7f27045b0783c887190545baba73aa25", size = 14185220, upload-time = "2025-09-09T15:56:32.175Z" },
+ { url = "https://files.pythonhosted.org/packages/22/f2/07bb754eb2ede9073f4054f7c0286b0d9d2e23982e090a80d478b26d35ca/numpy-2.3.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:396b254daeb0a57b1fe0ecb5e3cff6fa79a380fa97c8f7781a6d08cd429418fe", size = 5113918, upload-time = "2025-09-09T15:56:34.175Z" },
+ { url = "https://files.pythonhosted.org/packages/81/0a/afa51697e9fb74642f231ea36aca80fa17c8fb89f7a82abd5174023c3960/numpy-2.3.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:067e3d7159a5d8f8a0b46ee11148fc35ca9b21f61e3c49fbd0a027450e65a33b", size = 6647922, upload-time = "2025-09-09T15:56:36.149Z" },
+ { url = "https://files.pythonhosted.org/packages/5d/f5/122d9cdb3f51c520d150fef6e87df9279e33d19a9611a87c0d2cf78a89f4/numpy-2.3.3-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c02d0629d25d426585fb2e45a66154081b9fa677bc92a881ff1d216bc9919a8", size = 14281991, upload-time = "2025-09-09T15:56:40.548Z" },
+ { url = "https://files.pythonhosted.org/packages/51/64/7de3c91e821a2debf77c92962ea3fe6ac2bc45d0778c1cbe15d4fce2fd94/numpy-2.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9192da52b9745f7f0766531dcfa978b7763916f158bb63bdb8a1eca0068ab20", size = 16641643, upload-time = "2025-09-09T15:56:43.343Z" },
+ { url = "https://files.pythonhosted.org/packages/30/e4/961a5fa681502cd0d68907818b69f67542695b74e3ceaa513918103b7e80/numpy-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cd7de500a5b66319db419dc3c345244404a164beae0d0937283b907d8152e6ea", size = 16056787, upload-time = "2025-09-09T15:56:46.141Z" },
+ { url = "https://files.pythonhosted.org/packages/99/26/92c912b966e47fbbdf2ad556cb17e3a3088e2e1292b9833be1dfa5361a1a/numpy-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:93d4962d8f82af58f0b2eb85daaf1b3ca23fe0a85d0be8f1f2b7bb46034e56d7", size = 18579598, upload-time = "2025-09-09T15:56:49.844Z" },
+ { url = "https://files.pythonhosted.org/packages/17/b6/fc8f82cb3520768718834f310c37d96380d9dc61bfdaf05fe5c0b7653e01/numpy-2.3.3-cp312-cp312-win32.whl", hash = "sha256:5534ed6b92f9b7dca6c0a19d6df12d41c68b991cef051d108f6dbff3babc4ebf", size = 6320800, upload-time = "2025-09-09T15:56:52.499Z" },
+ { url = "https://files.pythonhosted.org/packages/32/ee/de999f2625b80d043d6d2d628c07d0d5555a677a3cf78fdf868d409b8766/numpy-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:497d7cad08e7092dba36e3d296fe4c97708c93daf26643a1ae4b03f6294d30eb", size = 12786615, upload-time = "2025-09-09T15:56:54.422Z" },
+ { url = "https://files.pythonhosted.org/packages/49/6e/b479032f8a43559c383acb20816644f5f91c88f633d9271ee84f3b3a996c/numpy-2.3.3-cp312-cp312-win_arm64.whl", hash = "sha256:ca0309a18d4dfea6fc6262a66d06c26cfe4640c3926ceec90e57791a82b6eee5", size = 10195936, upload-time = "2025-09-09T15:56:56.541Z" },
+ { url = "https://files.pythonhosted.org/packages/7d/b9/984c2b1ee61a8b803bf63582b4ac4242cf76e2dbd663efeafcb620cc0ccb/numpy-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f5415fb78995644253370985342cd03572ef8620b934da27d77377a2285955bf", size = 20949588, upload-time = "2025-09-09T15:56:59.087Z" },
+ { url = "https://files.pythonhosted.org/packages/a6/e4/07970e3bed0b1384d22af1e9912527ecbeb47d3b26e9b6a3bced068b3bea/numpy-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d00de139a3324e26ed5b95870ce63be7ec7352171bc69a4cf1f157a48e3eb6b7", size = 14177802, upload-time = "2025-09-09T15:57:01.73Z" },
+ { url = "https://files.pythonhosted.org/packages/35/c7/477a83887f9de61f1203bad89cf208b7c19cc9fef0cebef65d5a1a0619f2/numpy-2.3.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:9dc13c6a5829610cc07422bc74d3ac083bd8323f14e2827d992f9e52e22cd6a6", size = 5106537, upload-time = "2025-09-09T15:57:03.765Z" },
+ { url = "https://files.pythonhosted.org/packages/52/47/93b953bd5866a6f6986344d045a207d3f1cfbad99db29f534ea9cee5108c/numpy-2.3.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:d79715d95f1894771eb4e60fb23f065663b2298f7d22945d66877aadf33d00c7", size = 6640743, upload-time = "2025-09-09T15:57:07.921Z" },
+ { url = "https://files.pythonhosted.org/packages/23/83/377f84aaeb800b64c0ef4de58b08769e782edcefa4fea712910b6f0afd3c/numpy-2.3.3-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:952cfd0748514ea7c3afc729a0fc639e61655ce4c55ab9acfab14bda4f402b4c", size = 14278881, upload-time = "2025-09-09T15:57:11.349Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/a5/bf3db6e66c4b160d6ea10b534c381a1955dfab34cb1017ea93aa33c70ed3/numpy-2.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5b83648633d46f77039c29078751f80da65aa64d5622a3cd62aaef9d835b6c93", size = 16636301, upload-time = "2025-09-09T15:57:14.245Z" },
+ { url = "https://files.pythonhosted.org/packages/a2/59/1287924242eb4fa3f9b3a2c30400f2e17eb2707020d1c5e3086fe7330717/numpy-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b001bae8cea1c7dfdb2ae2b017ed0a6f2102d7a70059df1e338e307a4c78a8ae", size = 16053645, upload-time = "2025-09-09T15:57:16.534Z" },
+ { url = "https://files.pythonhosted.org/packages/e6/93/b3d47ed882027c35e94ac2320c37e452a549f582a5e801f2d34b56973c97/numpy-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8e9aced64054739037d42fb84c54dd38b81ee238816c948c8f3ed134665dcd86", size = 18578179, upload-time = "2025-09-09T15:57:18.883Z" },
+ { url = "https://files.pythonhosted.org/packages/20/d9/487a2bccbf7cc9d4bfc5f0f197761a5ef27ba870f1e3bbb9afc4bbe3fcc2/numpy-2.3.3-cp313-cp313-win32.whl", hash = "sha256:9591e1221db3f37751e6442850429b3aabf7026d3b05542d102944ca7f00c8a8", size = 6312250, upload-time = "2025-09-09T15:57:21.296Z" },
+ { url = "https://files.pythonhosted.org/packages/1b/b5/263ebbbbcede85028f30047eab3d58028d7ebe389d6493fc95ae66c636ab/numpy-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f0dadeb302887f07431910f67a14d57209ed91130be0adea2f9793f1a4f817cf", size = 12783269, upload-time = "2025-09-09T15:57:23.034Z" },
+ { url = "https://files.pythonhosted.org/packages/fa/75/67b8ca554bbeaaeb3fac2e8bce46967a5a06544c9108ec0cf5cece559b6c/numpy-2.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:3c7cf302ac6e0b76a64c4aecf1a09e51abd9b01fc7feee80f6c43e3ab1b1dbc5", size = 10195314, upload-time = "2025-09-09T15:57:25.045Z" },
+ { url = "https://files.pythonhosted.org/packages/11/d0/0d1ddec56b162042ddfafeeb293bac672de9b0cfd688383590090963720a/numpy-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:eda59e44957d272846bb407aad19f89dc6f58fecf3504bd144f4c5cf81a7eacc", size = 21048025, upload-time = "2025-09-09T15:57:27.257Z" },
+ { url = "https://files.pythonhosted.org/packages/36/9e/1996ca6b6d00415b6acbdd3c42f7f03ea256e2c3f158f80bd7436a8a19f3/numpy-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:823d04112bc85ef5c4fda73ba24e6096c8f869931405a80aa8b0e604510a26bc", size = 14301053, upload-time = "2025-09-09T15:57:30.077Z" },
+ { url = "https://files.pythonhosted.org/packages/05/24/43da09aa764c68694b76e84b3d3f0c44cb7c18cdc1ba80e48b0ac1d2cd39/numpy-2.3.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:40051003e03db4041aa325da2a0971ba41cf65714e65d296397cc0e32de6018b", size = 5229444, upload-time = "2025-09-09T15:57:32.733Z" },
+ { url = "https://files.pythonhosted.org/packages/bc/14/50ffb0f22f7218ef8af28dd089f79f68289a7a05a208db9a2c5dcbe123c1/numpy-2.3.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:6ee9086235dd6ab7ae75aba5662f582a81ced49f0f1c6de4260a78d8f2d91a19", size = 6738039, upload-time = "2025-09-09T15:57:34.328Z" },
+ { url = "https://files.pythonhosted.org/packages/55/52/af46ac0795e09657d45a7f4db961917314377edecf66db0e39fa7ab5c3d3/numpy-2.3.3-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94fcaa68757c3e2e668ddadeaa86ab05499a70725811e582b6a9858dd472fb30", size = 14352314, upload-time = "2025-09-09T15:57:36.255Z" },
+ { url = "https://files.pythonhosted.org/packages/a7/b1/dc226b4c90eb9f07a3fff95c2f0db3268e2e54e5cce97c4ac91518aee71b/numpy-2.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:da1a74b90e7483d6ce5244053399a614b1d6b7bc30a60d2f570e5071f8959d3e", size = 16701722, upload-time = "2025-09-09T15:57:38.622Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/9d/9d8d358f2eb5eced14dba99f110d83b5cd9a4460895230f3b396ad19a323/numpy-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2990adf06d1ecee3b3dcbb4977dfab6e9f09807598d647f04d385d29e7a3c3d3", size = 16132755, upload-time = "2025-09-09T15:57:41.16Z" },
+ { url = "https://files.pythonhosted.org/packages/b6/27/b3922660c45513f9377b3fb42240bec63f203c71416093476ec9aa0719dc/numpy-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ed635ff692483b8e3f0fcaa8e7eb8a75ee71aa6d975388224f70821421800cea", size = 18651560, upload-time = "2025-09-09T15:57:43.459Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/8e/3ab61a730bdbbc201bb245a71102aa609f0008b9ed15255500a99cd7f780/numpy-2.3.3-cp313-cp313t-win32.whl", hash = "sha256:a333b4ed33d8dc2b373cc955ca57babc00cd6f9009991d9edc5ddbc1bac36bcd", size = 6442776, upload-time = "2025-09-09T15:57:45.793Z" },
+ { url = "https://files.pythonhosted.org/packages/1c/3a/e22b766b11f6030dc2decdeff5c2fb1610768055603f9f3be88b6d192fb2/numpy-2.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:4384a169c4d8f97195980815d6fcad04933a7e1ab3b530921c3fef7a1c63426d", size = 12927281, upload-time = "2025-09-09T15:57:47.492Z" },
+ { url = "https://files.pythonhosted.org/packages/7b/42/c2e2bc48c5e9b2a83423f99733950fbefd86f165b468a3d85d52b30bf782/numpy-2.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:75370986cc0bc66f4ce5110ad35aae6d182cc4ce6433c40ad151f53690130bf1", size = 10265275, upload-time = "2025-09-09T15:57:49.647Z" },
+ { url = "https://files.pythonhosted.org/packages/6b/01/342ad585ad82419b99bcf7cebe99e61da6bedb89e213c5fd71acc467faee/numpy-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cd052f1fa6a78dee696b58a914b7229ecfa41f0a6d96dc663c1220a55e137593", size = 20951527, upload-time = "2025-09-09T15:57:52.006Z" },
+ { url = "https://files.pythonhosted.org/packages/ef/d8/204e0d73fc1b7a9ee80ab1fe1983dd33a4d64a4e30a05364b0208e9a241a/numpy-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:414a97499480067d305fcac9716c29cf4d0d76db6ebf0bf3cbce666677f12652", size = 14186159, upload-time = "2025-09-09T15:57:54.407Z" },
+ { url = "https://files.pythonhosted.org/packages/22/af/f11c916d08f3a18fb8ba81ab72b5b74a6e42ead4c2846d270eb19845bf74/numpy-2.3.3-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:50a5fe69f135f88a2be9b6ca0481a68a136f6febe1916e4920e12f1a34e708a7", size = 5114624, upload-time = "2025-09-09T15:57:56.5Z" },
+ { url = "https://files.pythonhosted.org/packages/fb/11/0ed919c8381ac9d2ffacd63fd1f0c34d27e99cab650f0eb6f110e6ae4858/numpy-2.3.3-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:b912f2ed2b67a129e6a601e9d93d4fa37bef67e54cac442a2f588a54afe5c67a", size = 6642627, upload-time = "2025-09-09T15:57:58.206Z" },
+ { url = "https://files.pythonhosted.org/packages/ee/83/deb5f77cb0f7ba6cb52b91ed388b47f8f3c2e9930d4665c600408d9b90b9/numpy-2.3.3-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9e318ee0596d76d4cb3d78535dc005fa60e5ea348cd131a51e99d0bdbe0b54fe", size = 14296926, upload-time = "2025-09-09T15:58:00.035Z" },
+ { url = "https://files.pythonhosted.org/packages/77/cc/70e59dcb84f2b005d4f306310ff0a892518cc0c8000a33d0e6faf7ca8d80/numpy-2.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ce020080e4a52426202bdb6f7691c65bb55e49f261f31a8f506c9f6bc7450421", size = 16638958, upload-time = "2025-09-09T15:58:02.738Z" },
+ { url = "https://files.pythonhosted.org/packages/b6/5a/b2ab6c18b4257e099587d5b7f903317bd7115333ad8d4ec4874278eafa61/numpy-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e6687dc183aa55dae4a705b35f9c0f8cb178bcaa2f029b241ac5356221d5c021", size = 16071920, upload-time = "2025-09-09T15:58:05.029Z" },
+ { url = "https://files.pythonhosted.org/packages/b8/f1/8b3fdc44324a259298520dd82147ff648979bed085feeacc1250ef1656c0/numpy-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d8f3b1080782469fdc1718c4ed1d22549b5fb12af0d57d35e992158a772a37cf", size = 18577076, upload-time = "2025-09-09T15:58:07.745Z" },
+ { url = "https://files.pythonhosted.org/packages/f0/a1/b87a284fb15a42e9274e7fcea0dad259d12ddbf07c1595b26883151ca3b4/numpy-2.3.3-cp314-cp314-win32.whl", hash = "sha256:cb248499b0bc3be66ebd6578b83e5acacf1d6cb2a77f2248ce0e40fbec5a76d0", size = 6366952, upload-time = "2025-09-09T15:58:10.096Z" },
+ { url = "https://files.pythonhosted.org/packages/70/5f/1816f4d08f3b8f66576d8433a66f8fa35a5acfb3bbd0bf6c31183b003f3d/numpy-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:691808c2b26b0f002a032c73255d0bd89751425f379f7bcd22d140db593a96e8", size = 12919322, upload-time = "2025-09-09T15:58:12.138Z" },
+ { url = "https://files.pythonhosted.org/packages/8c/de/072420342e46a8ea41c324a555fa90fcc11637583fb8df722936aed1736d/numpy-2.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:9ad12e976ca7b10f1774b03615a2a4bab8addce37ecc77394d8e986927dc0dfe", size = 10478630, upload-time = "2025-09-09T15:58:14.64Z" },
+ { url = "https://files.pythonhosted.org/packages/d5/df/ee2f1c0a9de7347f14da5dd3cd3c3b034d1b8607ccb6883d7dd5c035d631/numpy-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9cc48e09feb11e1db00b320e9d30a4151f7369afb96bd0e48d942d09da3a0d00", size = 21047987, upload-time = "2025-09-09T15:58:16.889Z" },
+ { url = "https://files.pythonhosted.org/packages/d6/92/9453bdc5a4e9e69cf4358463f25e8260e2ffc126d52e10038b9077815989/numpy-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:901bf6123879b7f251d3631967fd574690734236075082078e0571977c6a8e6a", size = 14301076, upload-time = "2025-09-09T15:58:20.343Z" },
+ { url = "https://files.pythonhosted.org/packages/13/77/1447b9eb500f028bb44253105bd67534af60499588a5149a94f18f2ca917/numpy-2.3.3-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:7f025652034199c301049296b59fa7d52c7e625017cae4c75d8662e377bf487d", size = 5229491, upload-time = "2025-09-09T15:58:22.481Z" },
+ { url = "https://files.pythonhosted.org/packages/3d/f9/d72221b6ca205f9736cb4b2ce3b002f6e45cd67cd6a6d1c8af11a2f0b649/numpy-2.3.3-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:533ca5f6d325c80b6007d4d7fb1984c303553534191024ec6a524a4c92a5935a", size = 6737913, upload-time = "2025-09-09T15:58:24.569Z" },
+ { url = "https://files.pythonhosted.org/packages/3c/5f/d12834711962ad9c46af72f79bb31e73e416ee49d17f4c797f72c96b6ca5/numpy-2.3.3-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0edd58682a399824633b66885d699d7de982800053acf20be1eaa46d92009c54", size = 14352811, upload-time = "2025-09-09T15:58:26.416Z" },
+ { url = "https://files.pythonhosted.org/packages/a1/0d/fdbec6629d97fd1bebed56cd742884e4eead593611bbe1abc3eb40d304b2/numpy-2.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:367ad5d8fbec5d9296d18478804a530f1191e24ab4d75ab408346ae88045d25e", size = 16702689, upload-time = "2025-09-09T15:58:28.831Z" },
+ { url = "https://files.pythonhosted.org/packages/9b/09/0a35196dc5575adde1eb97ddfbc3e1687a814f905377621d18ca9bc2b7dd/numpy-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8f6ac61a217437946a1fa48d24c47c91a0c4f725237871117dea264982128097", size = 16133855, upload-time = "2025-09-09T15:58:31.349Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/ca/c9de3ea397d576f1b6753eaa906d4cdef1bf97589a6d9825a349b4729cc2/numpy-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:179a42101b845a816d464b6fe9a845dfaf308fdfc7925387195570789bb2c970", size = 18652520, upload-time = "2025-09-09T15:58:33.762Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/c2/e5ed830e08cd0196351db55db82f65bc0ab05da6ef2b72a836dcf1936d2f/numpy-2.3.3-cp314-cp314t-win32.whl", hash = "sha256:1250c5d3d2562ec4174bce2e3a1523041595f9b651065e4a4473f5f48a6bc8a5", size = 6515371, upload-time = "2025-09-09T15:58:36.04Z" },
+ { url = "https://files.pythonhosted.org/packages/47/c7/b0f6b5b67f6788a0725f744496badbb604d226bf233ba716683ebb47b570/numpy-2.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:b37a0b2e5935409daebe82c1e42274d30d9dd355852529eab91dab8dcca7419f", size = 13112576, upload-time = "2025-09-09T15:58:37.927Z" },
+ { url = "https://files.pythonhosted.org/packages/06/b9/33bba5ff6fb679aa0b1f8a07e853f002a6b04b9394db3069a1270a7784ca/numpy-2.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:78c9f6560dc7e6b3990e32df7ea1a50bbd0e2a111e05209963f5ddcab7073b0b", size = 10545953, upload-time = "2025-09-09T15:58:40.576Z" },
+]
+
[[package]]
name = "packaging"
version = "25.0"
@@ -622,6 +713,24 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" },
]
+[[package]]
+name = "pvxslibs"
+version = "1.4.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "epicscorelibs" },
+ { name = "setuptools-dso" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/a2/30/c6ca9c4a61cab42a271d5d030a8f65cf9141979b5f0fbc2ce563b712d9e7/pvxslibs-1.4.0.tar.gz", hash = "sha256:1368cfd521edf15be2f8c4491c7ca3893b77712139f19b9578bdf39a65074a79", size = 664666, upload-time = "2025-07-31T08:40:41.559Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a0/b8/f4d6b3507ec8593d414c9d41932a76dca167cd04dd3585f78a9654e17e85/pvxslibs-1.4.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:8cbbd8c60d418e0c17f80612982b5546264a8477189ed732d26887abd76f9832", size = 2951643, upload-time = "2025-07-31T08:40:27.417Z" },
+ { url = "https://files.pythonhosted.org/packages/e4/4c/1024cd7f4da756619cef1ca02c9b92998106b82b81e19eee428cf5efb5a1/pvxslibs-1.4.0-cp312-cp312-manylinux2014_x86_64.whl", hash = "sha256:17798271ecf20160bd9c70de31e83be0e35d75c39162e28722b0a65ecaaa7dc7", size = 2658223, upload-time = "2025-07-31T08:44:48.436Z" },
+ { url = "https://files.pythonhosted.org/packages/fc/b5/a85daed16560780c99b99470177f2dcfaa95b5c68ad616683f4f6d6cae2b/pvxslibs-1.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:4571232ade601cfb9e2660d132cfc045831f7d66e72354cea6cc62beee6a2c79", size = 781156, upload-time = "2025-07-31T08:45:14.419Z" },
+ { url = "https://files.pythonhosted.org/packages/79/d3/5b18121d3181aeb3a6633bfa0e072acdf760ad8943b7cec5a54c0110b45f/pvxslibs-1.4.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:eb26b8e4f7a00d463c1b0727cb3e275671835b36caedbc4ec420bd06152d500f", size = 2951602, upload-time = "2025-07-31T08:42:42.709Z" },
+ { url = "https://files.pythonhosted.org/packages/b6/be/2878fe1cc695c3bf768ac2c885653660d934b9e031f513345df29cd26439/pvxslibs-1.4.0-cp313-cp313-manylinux2014_x86_64.whl", hash = "sha256:4a23b14ce7c69bbbb73b9d46380aec79b353d5136db87729d62099d7256dc859", size = 2658230, upload-time = "2025-07-31T08:48:24.771Z" },
+ { url = "https://files.pythonhosted.org/packages/91/c8/aaea17b4f2a3e51707998a7c49f28a5f3dfe6bc1e2b91f73ce3654eee899/pvxslibs-1.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:1587c014ec1fe753377b3199d1b561d742151c3a92db9d7481a3eea4840e6d37", size = 781213, upload-time = "2025-07-31T08:44:05.726Z" },
+]
+
[[package]]
name = "py"
version = "1.11.0"
@@ -959,6 +1068,27 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/e5/80/69756670caedcf3b9be597a6e12276a6cf6197076eb62aad0c608f8efce0/ruff-0.14.5-py3-none-win_arm64.whl", hash = "sha256:4b700459d4649e2594b31f20a9de33bc7c19976d4746d8d0798ad959621d64a4", size = 13433331, upload-time = "2025-11-13T19:58:48.434Z" },
]
+[[package]]
+name = "setuptools"
+version = "80.9.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/18/5d/3bf57dcd21979b887f014ea83c24ae194cfcd12b9e0fda66b957c69d1fca/setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c", size = 1319958, upload-time = "2025-05-27T00:56:51.443Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486, upload-time = "2025-05-27T00:56:49.664Z" },
+]
+
+[[package]]
+name = "setuptools-dso"
+version = "2.12.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "setuptools" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/36/ed/931a2b72f0403dc0f24180df21fef3ca773c70535249b4e3ade188b7b918/setuptools_dso-2.12.2.tar.gz", hash = "sha256:7afb76f93d13ce9da24502676d8f2d4dbc3da35c6245f95f27df9fa7445079a4", size = 21230, upload-time = "2025-03-21T16:08:34.979Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b9/36/c101788fad13e8ea65c5b3d3dee8ff996500800cd554ae6ff72143690247/setuptools_dso-2.12.2-py2.py3-none-any.whl", hash = "sha256:deb786b1cfac92f252a82df38e5129b1d9341b36885a01f64543bf3500734a21", size = 23756, upload-time = "2025-03-21T16:08:34.006Z" },
+]
+
[[package]]
name = "shellingham"
version = "1.5.4"
@@ -968,6 +1098,24 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" },
]
+[[package]]
+name = "softioc"
+version = "4.6.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "epicscorelibs" },
+ { name = "epicsdbbuilder" },
+ { name = "numpy" },
+ { name = "pvxslibs" },
+ { name = "pyyaml" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/f1/b9/23cd1b4df0fe853b8099d6f1b4c963b273eb492e7e330f4ff2135e888be7/softioc-4.6.1.tar.gz", hash = "sha256:6e3fb7c205b70d53f9c20e250404ae413339239285842107fbc4fa3881579af5", size = 90822, upload-time = "2025-04-22T10:38:38.094Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e3/28/a49cbc0f34da8bc219c9e8c2ca0b31e6444689255812719a406371e93c99/softioc-4.6.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4cfc8db83c05b62cac90e934f4b4e25abb0a8030a67169b77f9c9e8bc9f42dfa", size = 113094, upload-time = "2025-04-22T10:38:25.175Z" },
+ { url = "https://files.pythonhosted.org/packages/12/f7/9b4b430ac33759c0f225f84e265b197f936b993c4cfc85eb27d245a7cde0/softioc-4.6.1-cp312-cp312-manylinux2014_x86_64.whl", hash = "sha256:b35cc163340b30df9159ddead11fc0babdf30b7e8d757c3ef1bea4fba08cfa29", size = 118619, upload-time = "2025-04-22T10:38:26.542Z" },
+ { url = "https://files.pythonhosted.org/packages/5e/46/2bb58c5452c38f9dede53abf45fe51d23f775e022b79af3de60e946a1870/softioc-4.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:0e73422ae04e568b325c9887292ca3b04e29cb56f159b2a9693c68540e5f1b7f", size = 112523, upload-time = "2025-04-22T10:38:27.869Z" },
+]
+
[[package]]
name = "soupsieve"
version = "2.8"
@@ -981,11 +1129,13 @@ wheels = [
name = "techui-builder"
source = { editable = "." }
dependencies = [
+ { name = "epicsdbbuilder" },
{ name = "lxml" },
{ name = "phoebusgen" },
{ name = "pydantic" },
{ name = "pyyaml" },
{ name = "rich" },
+ { name = "softioc" },
{ name = "typer" },
]
@@ -1011,11 +1161,13 @@ dev = [
[package.metadata]
requires-dist = [
+ { name = "epicsdbbuilder", specifier = ">=1.5" },
{ name = "lxml", specifier = ">=5.4.0" },
{ name = "phoebusgen", specifier = ">=3.0.0" },
{ name = "pydantic", specifier = ">=2.11.7" },
{ name = "pyyaml", specifier = ">=6.0.2" },
{ name = "rich", specifier = ">=14.1.0" },
+ { name = "softioc", specifier = ">=4.6.1" },
{ name = "typer", specifier = ">=0.16.0" },
]