Skip to content

Commit

Permalink
Allow users to reset the list of created records
Browse files Browse the repository at this point in the history
Implemented a "ClearRecords" function that performs logic that was
previously only in some code for tests.
  • Loading branch information
AlexanderWells-diamond committed Oct 19, 2022
1 parent dc4a63f commit b5f5e0a
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Unreleased_
-----------

- `Allow "status" and "severity" on In record init <../../pull/111>`_
- `Allow users to reset the list of created records <../../pull/114>`_

4.1.0_ - 2022-08-05
-------------------
Expand Down
4 changes: 4 additions & 0 deletions docs/reference/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,10 @@ The following attributes allow more direct access to record creation.

See `../how-to/use-soft-records` for a full example of its usage.

.. function:: ClearRecords()
This can be used to remove all created records. This means the same record
names can be re-used for different record types.

Finally, the following function is used to load record definitions before
starting the IOC.

Expand Down
9 changes: 8 additions & 1 deletion softioc/builder.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import numpy

from .device_core import RecordLookup
from .softioc import dbLoadDatabase

from epicsdbbuilder import *
Expand Down Expand Up @@ -290,6 +291,12 @@ def LoadDatabase():
pythonSoftIoc.RecordWrapper.reset_builder()


def ClearRecords():
"""Delete all created record information, allowing new record creation"""
RecordLookup._RecordDirectory.clear()
ResetRecords()


# ----------------------------------------------------------------------------
# Record name configuration. A device name prefix must be specified.

Expand Down Expand Up @@ -317,7 +324,7 @@ def UnsetDevice():
'longStringIn', 'longStringOut',
'Action',
# Other builder support functions
'LoadDatabase',
'LoadDatabase', 'ClearRecords',
'SetDeviceName', 'UnsetDevice',
# Device support functions
'SetBlocking'
Expand Down
2 changes: 0 additions & 2 deletions softioc/softioc.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
from ctypes import *
from tempfile import NamedTemporaryFile

from epicsdbbuilder.recordset import recordset

from . import imports, device
from . import cothread_dispatcher

Expand Down
15 changes: 3 additions & 12 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
import pytest

# Must import softioc before epicsdbbuilder
from softioc.device_core import RecordLookup
from epicsdbbuilder import ResetRecords
from softioc.builder import ClearRecords

requires_cothread = pytest.mark.skipif(
sys.platform.startswith("win"), reason="Cothread doesn't work on windows"
Expand Down Expand Up @@ -88,20 +87,12 @@ def asyncio_ioc_override():
ioc.kill()
aioca_cleanup()

def _clear_records():
# Remove any records created at epicsdbbuilder layer
ResetRecords()
# And at pythonSoftIoc level
# TODO: Remove this hack and use use whatever comes out of
# https://github.com/dls-controls/pythonSoftIOC/issues/56
RecordLookup._RecordDirectory.clear()

@pytest.fixture(autouse=True)
def clear_records():
"""Deletes all records before and after every test"""
_clear_records()
ClearRecords()
yield
_clear_records()
ClearRecords()

@pytest.fixture(autouse=True)
def enable_code_coverage():
Expand Down
32 changes: 30 additions & 2 deletions tests/test_records.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
log,
create_random_prefix,
requires_cothread,
_clear_records,
WAVEFORM_LENGTH,
TIMEOUT,
select_and_recv,
Expand All @@ -19,6 +18,7 @@
from softioc import asyncio_dispatcher, builder, softioc
from softioc import alarm
from softioc.device import SetBlocking
from softioc.device_core import LookupRecord, LookupRecordList

# Test file for miscellaneous tests related to records

Expand All @@ -38,7 +38,6 @@ def test_records(tmp_path):
# Ensure we definitely unload all records that may be hanging over from
# previous tests, then create exactly one instance of expected records.
from sim_records import create_records
_clear_records()
create_records()

path = str(tmp_path / "records.db")
Expand Down Expand Up @@ -228,6 +227,35 @@ def test_setting_alarm_invalid_keywords(creation_func):

assert e.value.args[0] == 'Can\'t specify both status and STAT'

def test_clear_records():
"""Test that clearing the known records allows creation of a record of the
same name afterwards"""

device_name = create_random_prefix()
builder.SetDeviceName(device_name)

record_name = "NEW-RECORD"

builder.aOut(record_name)

# First check that we cannot create two of the same name
with pytest.raises(AssertionError):
builder.aOut(record_name)

builder.ClearRecords()

# Then confirm we can create one of this name
builder.aOut(record_name)

# Finally prove that the underlying record holder contains only one record
# Records are stored as full device:record name
full_name = device_name + ":" + record_name
assert LookupRecord(full_name)
assert len(LookupRecordList()) == 1
for key, val in LookupRecordList():
assert key == full_name



def validate_fixture_names(params):
"""Provide nice names for the out_records fixture in TestValidate class"""
Expand Down

0 comments on commit b5f5e0a

Please sign in to comment.