Skip to content

Commit

Permalink
Merge pull request #127 from klauer/fix_iocmanager
Browse files Browse the repository at this point in the history
FIX/TST: avoid parsing commented lines in iocmanager config
  • Loading branch information
klauer authored Apr 29, 2022
2 parents 97b22a6 + 8a20ba2 commit 99d2c32
Show file tree
Hide file tree
Showing 3 changed files with 258 additions and 4 deletions.
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.4.0
rev: v4.2.0
hooks:
- id: no-commit-to-branch
- id: trailing-whitespace
Expand All @@ -18,11 +18,11 @@ repos:
- id: debug-statements

- repo: https://gitlab.com/pycqa/flake8.git
rev: 3.9.0
rev: 3.9.2
hooks:
- id: flake8

- repo: https://github.com/timothycrosley/isort
rev: 5.8.0
rev: 5.10.1
hooks:
- id: isort
15 changes: 14 additions & 1 deletion whatrecord/iocmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ def parse_config(lines: List[str]) -> List[IocInfoDict]:
"""
Parse an IOC manager config to get its IOCs.
The parsing here is a bit weak when it comes to syntax errors. This is
generally not a problem as these files are almost entirely written out by
the IOC Manager GUI / CLI tools. Occasionally, a user may edit the file
manually and introduce syntax errors on certain lines, and this will
attempt to skip it as best it can.
Parameters
----------
lines : list of str
Expand All @@ -48,14 +54,21 @@ def parse_config(lines: List[str]) -> List[IocInfoDict]:
continue
if not loading:
continue
if line.lstrip().startswith("#"):
continue
if "id:" in line:
if "}" in line:
# {id: ... } in a single line
entries.append(line)
else:
# {id: ...
# ... }
entry = line
elif entry is not None:
entry += line
if "}" in entry:
# {id: ...
# ... } <-- closing line
entries.append(entry)
entry = None

Expand All @@ -67,7 +80,7 @@ def fix_entry(entry):
try:
result.append(fix_entry(entry))
except Exception:
logger.exception("Failed to fix up IOC manager entry: %s", entry)
logger.error("Failed to fix up IOC manager entry: %s", entry)

return result

Expand Down
241 changes: 241 additions & 0 deletions whatrecord/tests/test_iocmanager_loader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
import textwrap

import pytest

from .. import iocmanager


def test_parse_empty():
assert iocmanager.parse_config([]) == []


@pytest.mark.parametrize(
"source, expected",
[
pytest.param(
textwrap.dedent(
"""\
COMMITHOST = "psbuild-rhel7-01"
hosts = [
'amo-console',
'ioc-amo-gige01',
'ioc-amo-gige02',
'ioc-amo-gige03',
'ioc-amo-hv1',
'ioc-amo-hv2',
'ioc-amo-kbo-lvdt',
'ioc-amo-lampenc01',
'ioc-amo-las1',
'ioc-amo-misc01',
'ioc-amo-mot01',
'ioc-amo-sdl',
'ioc-amo-slits',
'ioc-amo-uniq',
'ioc-amo-vacuum',
'ioc-det-pnccd01',
]
procmgr_config = [
{id:'ioc-amo-gige-01', host: 'ioc-amo-gige01', port: 30011, dir: 'ioc/amo/gigECam/R2.3.3',
history: ['ioc/amo/gigECam/R2.3.3', '/reg/neh/home/sstubbs/work/amo/gigECam/current']},
{id:'ioc-amo-gige-05', host: 'ioc-amo-gige01', port: 30015, dir: 'ioc/amo/gigECam/R2.3.3',
history: ['ioc/amo/gigECam/R2.3.3']},
{id:'ioc-amo-gige-06', host: 'ioc-amo-gige01', port: 30016, dir: 'ioc/amo/gigECam/R2.3.3',
history: ['ioc/amo/gigECam/R2.3.3']},
{id:'ioc-amo-gige-08', host: 'ioc-amo-gige01', port: 30029, dir: 'ioc/amo/gigECam/R2.3.3',
history: ['ioc/amo/gigECam/R2.3.3']},
{id:'ioc-amo-gige-09', host: 'ioc-amo-gige01', port: 30017, dir: 'ioc/amo/gigECam/R2.3.3',
history: ['ioc/amo/gigECam/R2.3.3']},
{id:'ioc-amo-usr-acromag', host: 'ioc-amo-gige01', port: 30001,
dir: 'ioc/amo/pciAcromag/R1.0.4',
history: ['ioc/amo/pciAcromag/R1.0.4']},
{id:'ioc-amo-gige-02', host: 'ioc-amo-gige02', port: 30012, dir: 'ioc/amo/gigECam/R2.3.3',
history: ['ioc/amo/gigECam/R2.3.3']},
{id:'ioc-amo-gige-03', host: 'ioc-amo-gige02', port: 30013, dir: 'ioc/amo/gigECam/R2.3.3',
history: ['ioc/amo/gigECam/R2.3.3']},
]
""",
),
[
{
"id": "ioc-amo-gige-01",
"host": "ioc-amo-gige01",
"port": 30011,
"dir": "ioc/amo/gigECam/R2.3.3",
"history": [
"ioc/amo/gigECam/R2.3.3",
"/reg/neh/home/sstubbs/work/amo/gigECam/current",
],
},
{
"id": "ioc-amo-gige-05",
"host": "ioc-amo-gige01",
"port": 30015,
"dir": "ioc/amo/gigECam/R2.3.3",
"history": ["ioc/amo/gigECam/R2.3.3"],
},
{
"id": "ioc-amo-gige-06",
"host": "ioc-amo-gige01",
"port": 30016,
"dir": "ioc/amo/gigECam/R2.3.3",
"history": ["ioc/amo/gigECam/R2.3.3"],
},
{
"id": "ioc-amo-gige-08",
"host": "ioc-amo-gige01",
"port": 30029,
"dir": "ioc/amo/gigECam/R2.3.3",
"history": ["ioc/amo/gigECam/R2.3.3"],
},
{
"id": "ioc-amo-gige-09",
"host": "ioc-amo-gige01",
"port": 30017,
"dir": "ioc/amo/gigECam/R2.3.3",
"history": ["ioc/amo/gigECam/R2.3.3"],
},
{
"id": "ioc-amo-usr-acromag",
"host": "ioc-amo-gige01",
"port": 30001,
"dir": "ioc/amo/pciAcromag/R1.0.4",
"history": ["ioc/amo/pciAcromag/R1.0.4"],
},
{
"id": "ioc-amo-gige-02",
"host": "ioc-amo-gige02",
"port": 30012,
"dir": "ioc/amo/gigECam/R2.3.3",
"history": ["ioc/amo/gigECam/R2.3.3"],
},
{
"id": "ioc-amo-gige-03",
"host": "ioc-amo-gige02",
"port": 30013,
"dir": "ioc/amo/gigECam/R2.3.3",
"history": ["ioc/amo/gigECam/R2.3.3"],
},
],
id="basic",
),
pytest.param(
textwrap.dedent(
"""\
COMMITHOST = "psbuild-rhel7-01"
hosts = [
'amo-console',
'ioc-amo-gige01',
'ioc-amo-gige02',
'ioc-amo-gige03',
'ioc-amo-hv1',
'ioc-amo-hv2',
'ioc-amo-kbo-lvdt',
'ioc-amo-lampenc01',
'ioc-amo-las1',
'ioc-amo-misc01',
'ioc-amo-mot01',
'ioc-amo-sdl',
'ioc-amo-slits',
'ioc-amo-uniq',
'ioc-amo-vacuum',
'ioc-det-pnccd01',
]
procmgr_config = [
{id:'ioc-mec-gige11', host: 'ioc-mec-las-gige02',
port: 32511, dir: 'ioc/mec/gigECam/R1.1.1',
disable: True, alias: 'Gige Long Pulse 1',
history: ['ioc/mec/gigECam/R0.1.9']},
# {id:'ioc-mec-gige12', host: 'ioc-mec-las-gige02', port: 32512,
# dir: 'ioc/mec/gigECam/R1.1.1', alias: 'Gige Long Pulse 2',
# history: ['ioc/mec/gigECam/R0.1.9']},
{id:'ioc-mec-gige12', host: 'ioc-mec-las-gige02', port: 32512,
dir: '/cds/userpath', alias: 'Gige Long Pulse 2',
history: ['ioc/mec/gigECam/R0.1.9']},
]
""",
),
[
{
"id": "ioc-mec-gige11",
"host": "ioc-mec-las-gige02",
"port": 32511,
"dir": "ioc/mec/gigECam/R1.1.1",
"disable": True,
"alias": "Gige Long Pulse 1",
"history": ["ioc/mec/gigECam/R0.1.9"],
},
{
"id": "ioc-mec-gige12",
"host": "ioc-mec-las-gige02",
"port": 32512,
"dir": "/cds/userpath",
"alias": "Gige Long Pulse 2",
"history": ["ioc/mec/gigECam/R0.1.9"],
},
],
id="commented",
),
]
)
def test_parse(source: str, expected: list, caplog: pytest.LogCaptureFixture):
print(source)
# print(source.splitlines())
caplog.set_level("WARNING", logger=iocmanager.logger.name)
assert iocmanager.parse_config(source.splitlines()) == expected
assert not caplog.records, "No failure to parse messages"


@pytest.mark.parametrize(
"source",
[
pytest.param(
textwrap.dedent(
"""\
procmgr_config=[
syntax error id:'ioc-amo-gige-01', host: 'ioc-amo-gige01',
port: 30011, dir: 'ioc/amo/gigECam/R2.3.3',
history: ['ioc/amo/gigECam/R2.3.3',
'/reg/neh/home/sstubbs/work/amo/gigECam/current']},
]
""",
),
id="syntax-error-1"
),
pytest.param(
textwrap.dedent(
"""\
procmgr_config=[
{id:ioc-amo-gige-01', host: 'ioc-amo-gige01', port: 30011,
dir: 'ioc/amo/gigECam/R2.3.3',
history: ['ioc/amo/gigECam/R2.3.3',
'/reg/neh/home/sstubbs/work/amo/gigECam/current']},
]
""",
),
id="syntax-error-2"
),
pytest.param(
textwrap.dedent(
"""\
procmgr_config=[
{id:ioc-amo-gige-01', host: 'ioc-amo-gige01', port: 30011,
dir: 'ioc/amo/gigECam/R2.3.3',
history; ['ioc/amo/gigECam/R2.3.3',
'/reg/neh/home/sstubbs/work/amo/gigECam/current']},
]
""",
),
id="syntax-error-3"
),
]
)
def test_parse_failure(source: str, caplog: pytest.LogCaptureFixture):
print(source)
# print(source.splitlines())
caplog.set_level("WARNING", logger=iocmanager.logger.name)
assert iocmanager.parse_config(source.splitlines()) == []
assert len(caplog.records) == 1, "Failure to parse id line"

0 comments on commit 99d2c32

Please sign in to comment.