chore: use camelcase name in gui

This commit is contained in:
Benjamin Labrecque
2026-07-28 09:45:48 +02:00
parent 0bf7f179de
commit e42f162c26
25 changed files with 82 additions and 80 deletions
+1 -2
View File
@@ -30,7 +30,6 @@ class ServiceCreator:
name: str,
ioc_owner: str,
ioc_description: str,
ui_name: str,
ui_filename: str,
):
self.repo_manager.assert_clean_repo()
@@ -43,7 +42,7 @@ class ServiceCreator:
self.ctx.iocs_overview.add_ioc(service, description=ioc_description)
self.ctx.master_ioc_subs.update_content(service_name=service.name_upper)
self.ctx.service_manager_ui.update_xml(
service=service, ui_name=ui_name, ui_filename=ui_filename
service=service, service_name_camel=service.name_camel, ui_filename=ui_filename
)
branch_name = f"feature/add-service-{service.dir_name}"
+9 -3
View File
@@ -10,6 +10,10 @@ class Service(BaseModel):
ioc_port: int
status: ServiceStatus
@property
def name_camel(self):
return self.name
@property
def name_upper(self):
return self.name.upper()
@@ -27,7 +31,7 @@ class Service(BaseModel):
return self.name.lower()
def to_dict(self):
return {"name": self.name_lower, "ioc_port": self.ioc_port, "status": str(self.status)}
return {"name": self.name_camel, "ioc_port": self.ioc_port, "status": str(self.status)}
class Config:
use_enum_values = True
@@ -35,6 +39,8 @@ class Service(BaseModel):
@field_validator("name")
@classmethod
def validate_name_chars(cls, value: str) -> str:
if not re.match(r"^[a-z0-9-]+$", value):
raise ValueError("name can only contain lowercase letters, numbers, and dashes")
if not re.match(r"^[a-zA-Z0-9-]+$", value):
raise ValueError(
"name can only contain uppercase and lowercase letters, numbers, and dashes"
)
return value
+8 -6
View File
@@ -17,15 +17,17 @@ class ServiceManagerUI(BaseModel):
tree = ET.parse(path)
return ServiceManagerUI(tree=tree)
def update_xml(self, service: Service, ui_name: str, ui_filename: str) -> None:
def update_xml(self, service: Service, service_name_camel: str, ui_filename: str) -> None:
num_macro_elements = self._update_macro(
service=service, ui_name=ui_name, ui_filename=ui_filename
service=service, service_name_camel=service_name_camel, ui_filename=ui_filename
)
self._update_heights(num_macro_elements=num_macro_elements)
def _update_macro(self, service: Service, ui_name: str, ui_filename: str) -> int:
def _update_macro(self, service: Service, service_name_camel: str, ui_filename: str) -> int:
new_macro_element = _ServiceManagerUIMacroElement(
service_name_upper=service.name_upper, ui_name=ui_name, ui_filename=ui_filename
service_name_upper=service.name_upper,
service_name_camel=service_name_camel,
ui_filename=ui_filename,
)
num_macro_elements = None
@@ -125,7 +127,7 @@ class ServiceManagerUI(BaseModel):
class _ServiceManagerUIMacroElement(BaseModel):
service_name_upper: str
ui_name: str
service_name_camel: str
panel: int = 1
svc_exist: int = 1
ui_filename: str
@@ -134,7 +136,7 @@ class _ServiceManagerUIMacroElement(BaseModel):
return (
f"IOC=AGEBD-CPCL-{self.service_name_upper},"
f"service={self.service_name_upper},"
f"name={self.ui_name},"
f"name={self.service_name_camel},"
f"panel={self.panel},"
f"svc_exist={self.svc_exist},"
f"panelcmd=A_BD_{self.ui_filename}.ui"
+4 -8
View File
@@ -20,7 +20,10 @@ REPO_ROOT = get_git_root(__file__)
)
def add(
name: str = typer.Option(
..., "--name", "-n", help="Must only contain lowercase characters and dashes"
...,
"--name",
"-n",
help="Camelcase name of the service. The name will be used as is in the gui, and converted to uppercase/lowercase where necessary",
),
ioc_owner: str = typer.Option(
...,
@@ -35,12 +38,6 @@ def add(
"-d",
help="See <repo-root>/docs/user/ioc/iocs_overview.md for examples",
),
ui_name: str = typer.Option(
...,
"--ui-name",
help="This is the name that will be used for the service in the UI. "
"See <repo-root>/qt/A_BD_ServiceManager.ui for examples",
),
ui_filename: str = typer.Option(
...,
"--ui-filename",
@@ -55,7 +52,6 @@ def add(
name=name,
ioc_owner=ioc_owner,
ioc_description=ioc_description,
ui_name=ui_name,
ui_filename=ui_filename,
)
@@ -1,8 +1,8 @@
next_available_ioc_port: 50002
services:
- name: master
- name: Master
ioc_port: 50000
status: active
- name: test-service
- name: TestService99-X00
ioc_port: 50001
status: active
@@ -1,4 +1,4 @@
| IOC NAME | Description |
|---|---|
| AGEBD-CPCL-MASTER | IOC providing PVs ... |
| AGEBD-CPCL-TEST-SERVICE | Test Description |
| AGEBD-CPCL-TESTSERVICE99-X00 | Test Description |
@@ -138,7 +138,7 @@ caLabel[statusTip="Operation"]{
</rect>
</property>
<property name="macro">
<string>IOC=AGEBD-CPCL-DBPM3CURR,service=DBPM3CURR,name=DBPM3Current,panel=1,svc_exist=1,panelcmd=A_BD_DBPM3Current.ui;IOC=AGEBD-CPCL-TAUBPM,service=TAUBPM,name=LifetimeBPM,panel=1,svc_exist=1,panelcmd=A_BD_LifetimeBPM.ui;IOC=AGEBD-CPCL-TAUPCT,service=TAUPCT,name=LifetimePCT,panel=1,svc_exist=1,panelcmd=A_BD_LifetimePCT.ui;IOC=AGEBD-CPCL-TIMING,service=TIMING,name=Timing,panel=1,svc_exist=1,panelcmd=A_BD_Timing.ui;IOC=AGEBD-CPCL-SCRUBBING,service=SCRUBBING,name=Scrubbing,panel=1,svc_exist=1,panelcmd=A_BD_Scrubbing.ui;IOC=AGEBD-CPCL-INJECTIONGUARD,service=INJECTIONGUARD,name=InjectionGuard,panel=1,svc_exist=1,panelcmd=A_BD_InjectionGuard.ui;IOC=AGEBD-CPCL-POSTMORTEMLOG,service=POSTMORTEMLOG,name=PostMortemLog,panel=1,svc_exist=1,panelcmd=A_BD_PostMortemLog.ui;IOC=AGEBD-CPCL-TUNEBUMP,service=TUNEBUMP,name=TuneBump,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui;IOC=AGEBD-CPCL-PLOTS,service=PLOTS,name=Plots,panel=0,svc_exist=1,panelcmd=A_BD_Plots.ui;IOC=AGEBD-CPCL-ORBITBUMP,service=ORBITBUMP,name=OrbitBump,panel=1,svc_exist=0,panelcmd=A_BD_OrbitBump.ui;IOC=AGEBD-CPCL-TUNEFBX,service=TUNEFBX,name=Hor. Tune Feedback,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui;IOC=AGEBD-CPCL-TUNEFBY,service=TUNEFBY,name=Ver. Tune Feedback,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui;IOC=AGEBD-CPCL-TEST-SERVICE,service=TEST-SERVICE,name=Test Service Ui Name,panel=1,svc_exist=1,panelcmd=A_BD_TestService.ui</string>
<string>IOC=AGEBD-CPCL-DBPM3CURR,service=DBPM3CURR,name=DBPM3Current,panel=1,svc_exist=1,panelcmd=A_BD_DBPM3Current.ui;IOC=AGEBD-CPCL-TAUBPM,service=TAUBPM,name=LifetimeBPM,panel=1,svc_exist=1,panelcmd=A_BD_LifetimeBPM.ui;IOC=AGEBD-CPCL-TAUPCT,service=TAUPCT,name=LifetimePCT,panel=1,svc_exist=1,panelcmd=A_BD_LifetimePCT.ui;IOC=AGEBD-CPCL-TIMING,service=TIMING,name=Timing,panel=1,svc_exist=1,panelcmd=A_BD_Timing.ui;IOC=AGEBD-CPCL-SCRUBBING,service=SCRUBBING,name=Scrubbing,panel=1,svc_exist=1,panelcmd=A_BD_Scrubbing.ui;IOC=AGEBD-CPCL-INJECTIONGUARD,service=INJECTIONGUARD,name=InjectionGuard,panel=1,svc_exist=1,panelcmd=A_BD_InjectionGuard.ui;IOC=AGEBD-CPCL-POSTMORTEMLOG,service=POSTMORTEMLOG,name=PostMortemLog,panel=1,svc_exist=1,panelcmd=A_BD_PostMortemLog.ui;IOC=AGEBD-CPCL-TUNEBUMP,service=TUNEBUMP,name=TuneBump,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui;IOC=AGEBD-CPCL-PLOTS,service=PLOTS,name=Plots,panel=0,svc_exist=1,panelcmd=A_BD_Plots.ui;IOC=AGEBD-CPCL-ORBITBUMP,service=ORBITBUMP,name=OrbitBump,panel=1,svc_exist=0,panelcmd=A_BD_OrbitBump.ui;IOC=AGEBD-CPCL-TUNEFBX,service=TUNEFBX,name=Hor. Tune Feedback,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui;IOC=AGEBD-CPCL-TUNEFBY,service=TUNEFBY,name=Ver. Tune Feedback,panel=1,svc_exist=1,panelcmd=A_BD_TuneBump.ui;IOC=AGEBD-CPCL-TESTSERVICE99-X00,service=TESTSERVICE99-X00,name=TestService99-X00,panel=1,svc_exist=1,panelcmd=A_BD_TestService.ui</string>
</property>
<property name="filename" stdset="0">
<string notr="true">A_BD_ServiceManager_inc.ui</string>
+4 -4
View File
@@ -30,7 +30,7 @@
<number>0</number>
</property>
<property name="channel" stdset="0">
<string>AGEBD-TEST-SERVICE$(AGEBD_ENV_SUFFIX):AO</string>
<string>AGEBD-TESTSERVICE99-X00$(AGEBD_ENV_SUFFIX):AO</string>
</property>
<property name="maxValue">
<double>9.000000000000000</double>
@@ -49,10 +49,10 @@
</rect>
</property>
<property name="text">
<string>Toggle AGEBD-ALH$(AGEBD_ENV_SUFFIX):TEST-SERVICE-ONOFF</string>
<string>Toggle AGEBD-ALH$(AGEBD_ENV_SUFFIX):TESTSERVICE99-X00-ONOFF</string>
</property>
<property name="channel" stdset="0">
<string>AGEBD-ALH$(AGEBD_ENV_SUFFIX):TEST-SERVICE-ONOFF</string>
<string>AGEBD-ALH$(AGEBD_ENV_SUFFIX):TESTSERVICE99-X00-ONOFF</string>
</property>
</widget>
<widget class="QLabel" name="label">
@@ -70,7 +70,7 @@
</font>
</property>
<property name="text">
<string>Value of AGEBD-TEST-SERVICE$(AGEBD_ENV_SUFFIX):AO</string>
<string>Value of AGEBD-TESTSERVICE99-X00$(AGEBD_ENV_SUFFIX):AO</string>
</property>
</widget>
</widget>
@@ -1,3 +1,3 @@
hla_apps:
- MASTER
- TEST-SERVICE
- TESTSERVICE99-X00
@@ -1,5 +1,5 @@
file MASTER.template {
pattern { SUFFIX SERVICE STARTON AUTOOFF }
{ "{{ agebd_env_suffix }}", "MASTER" , "0", "30" }
{ "{{ agebd_env_suffix }}", "TEST-SERVICE" , "0", "0" }
{ "{{ agebd_env_suffix }}", "TESTSERVICE99-X00" , "0", "0" }
}
@@ -1,4 +0,0 @@
file TEST-SERVICE.template {
pattern { DEVICE }
{ AGEBD-TEST-SERVICE{{ agebd_env_suffix }} }
}
@@ -1,7 +1,7 @@
[project]
name = "agebd-test-service"
name = "agebd-testservice99-x00"
version = "0.1.0"
description = "AGEBD-TEST-SERVICE Service"
description = "AGEBD-TESTSERVICE99-X00 Service"
requires-python = "==3.10.*"
dependencies = [
"agebd",
@@ -3,8 +3,8 @@ import typer
from agebd.enums import LogLevel
from agebd.runner import CallbackRunner
from agebd.utils import init_logging
from agebd_test_service import PVs, Service
from agebd_test_service.service import SERVICE_NAME
from agebd_testservice99_x00 import PVs, Service
from agebd_testservice99_x00.service import SERVICE_NAME
def main(
@@ -9,14 +9,14 @@ from agebd.utils import printgetversion
__version__ = printgetversion(__file__)
SERVICE_NAME = "TEST-SERVICE"
SERVICE_NAME = "TESTSERVICE99-X00"
PV = get_pv_class(service_name=SERVICE_NAME)
class PVs(BasePVs):
# Option 1:
## Service specific PVs from dedicated IOC
my_pv1 = PV("AGEBD-TEST-SERVICE:AO") # TODO: is this a good PV to use?
my_pv1 = PV("AGEBD-TESTSERVICE99-X00:AO") # TODO: is this a good PV to use?
## Service specific PVs from other IOCs
# ...
@@ -32,14 +32,14 @@ class PVs(BasePVs):
# Option 2:
## Service specific PVs from dedicated IOC
self.my_pv2 = PV("AGEBD-TEST-SERVICE:BO") # TODO: is this a good PV to use?
self.my_pv2 = PV("AGEBD-TESTSERVICE99-X00:BO") # TODO: is this a good PV to use?
## Service specific PVs from other IOCs
# ...
# TODO: class attribute names usually lowercase
# usually it is advisable to trigger the mainloop of a service on changes of certain PVs:
self.CallbackPV = PV("AGEBD-TEST-SERVICE:CALLBACK", auto_monitor=dbr.DBE_VALUE)
self.CallbackPV = PV("AGEBD-TESTSERVICE99-X00:CALLBACK", auto_monitor=dbr.DBE_VALUE)
class Service(BaseService[PVs]):
@@ -1,4 +1,4 @@
from agebd_test_service import PVs, Service
from agebd_testservice99_x00 import PVs, Service
def test_app():
@@ -0,0 +1,4 @@
file TESTSERVICE99-X00.template {
pattern { DEVICE }
{ AGEBD-TESTSERVICE99-X00{{ agebd_env_suffix }} }
}
@@ -34,4 +34,4 @@ record(bo, "$(DEVICE):CALLBACK") {
field(OSV, "NO_ALARM")
field(VAL, "1")
field(PINI, "YES")
}
}
@@ -1,11 +1,11 @@
[Unit]
Description=AGEBD-SERVICE-TEST-SERVICE
Description=AGEBD-SERVICE-TESTSERVICE99-X00
After=network.target
[Service]
Environment=AGEBD_ENV={{ agebd_env }}
Environment=PYTHONUNBUFFERED=1
ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh TEST-SERVICE
ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh TESTSERVICE99-X00
Restart=no
[Install]
@@ -13,5 +13,5 @@ WantedBy=default.target
# https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html
# systemctl --user daemon-reload
# systemctl --user enable /sls/bd/bin/systemd/AGEBD-SERVICE-TEST-SERVICE.service
# systemctl --user start AGEBD-SERVICE-TEST-SERVICE
# systemctl --user enable /sls/bd/bin/systemd/AGEBD-SERVICE-TESTSERVICE99-X00.service
# systemctl --user start AGEBD-SERVICE-TESTSERVICE99-X00
@@ -1,5 +1,5 @@
next_available_ioc_port: 50001
services:
- name: master
- name: Master
ioc_port: 50000
status: active
+2 -3
View File
@@ -68,16 +68,15 @@ def test_add_new_service(tmp_path, mocker: MockerFixture):
creator = ServiceCreator(ctx=ctx, repo_manager=mocker.Mock(spec=GitRepoManager))
creator.add_service(
name="test-service",
name="TestService99-X00",
ioc_owner="test_user",
ioc_description="Test Description",
ui_name="Test Service Ui Name",
ui_filename="TestService",
)
assert_are_dir_trees_equal(tmp_path, EXPECTED_OUTPUT_DIR, tmp_path)
files_to_stage = ctx._write_paths.get_files_to_stage(service_dir_name="test-service")
files_to_stage = ctx._write_paths.get_files_to_stage(service_dir_name="testservice99-x00")
assert_all_files_staged(tmp_path, files_to_stage)
+29 -29
View File
@@ -1,89 +1,89 @@
next_available_ioc_port: 50029
services:
- name: master
- name: Master
ioc_port: 50000
status: active
- name: nturns
- name: NTurns
ioc_port: 50001
status: active
- name: dbpm3curr
- name: DBPM3Current
ioc_port: 50002
status: active
- name: taubpm
- name: TauBPM
ioc_port: 50003
status: active
- name: taupct
- name: TauPCT
ioc_port: 50004
status: active
- name: scrubbing
- name: Scrubbing
ioc_port: 50005
status: active
- name: timing
- name: Timing
ioc_port: 50006
status: active
- name: tune
- name: Tune
ioc_port: 50007
status: active
- name: injectionguard
- name: InjectionGuard
ioc_port: 50008
status: active
- name: postmortemlog
- name: PostMortemLog
ioc_port: 50009
status: active
- name: tunebump
- name: TuneBump
ioc_port: 50010
status: active
- name: plots
- name: Plots
ioc_port: 50011
status: active
- name: orbitbump
- name: OrbitBump
ioc_port: 50012
status: inactive
- name: topuptool
- name: TopUpTool
ioc_port: 50013
status: active
- name: shifttool
- name: Shifttool
ioc_port: 50014
status: active
- name: beamtransferchecks
- name: BeamTransferChecks
ioc_port: 50015
status: inactive
- name: tunefbx
- name: TuneFBx
ioc_port: 50016
status: active
- name: tunefby
- name: TuneFBy
ioc_port: 50017
status: active
- name: opticsff-x02s
- name: OpticsFF-x02s
ioc_port: 50018
status: inactive
- name: opticsff-x03m
- name: OpticsFF-x03m
ioc_port: 50019
status: inactive
- name: opticsff-x04s
- name: OpticsFF-x04s
ioc_port: 50020
status: inactive
- name: opticsff-x05l
- name: OpticsFF-x05l
ioc_port: 50021
status: inactive
- name: opticsff-x06s
- name: OpticsFF-x06s
ioc_port: 50022
status: inactive
- name: opticsff-x07m
- name: OpticsFF-x07m
ioc_port: 50023
status: inactive
- name: opticsff-x08s
- name: OpticsFF-x08s
ioc_port: 50024
status: inactive
- name: opticsff-x09l
- name: OpticsFF-x09l
ioc_port: 50025
status: inactive
- name: opticsff-x10s
- name: OpticsFF-x10s
ioc_port: 50026
status: inactive
- name: opticsff-x11m
- name: OpticsFF-x11m
ioc_port: 50027
status: inactive
- name: opticsff-x12s
- name: OpticsFF-x12s
ioc_port: 50028
status: inactive