Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

newSpecFile should update scan_id if provided #307

Merged
merged 4 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Fixes
-----

* Application new_bluesky_environment would crash when requests package not found.
* Function newSpecFile did not update scan_id in some cases.

Maintenance
------------
Expand Down
27 changes: 27 additions & 0 deletions bluesky/instrument/callbacks/spec_data_file_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,32 @@ def spec_comment(comment, doc=None):
APS_fw.spec_comment(comment, doc, specwriter)


def RE_finder():
"""
Find RunEngine object from namespaces of the stack.

* Search backwards through each frame in the stack.
* Find any RunEngine objects.
* Prefer one with name 'RE'.
* Otherwise, pick the first one.
* Otherwise, return 'None'.

suggestion: Hoist to apstools.utils
"""
import inspect
from bluesky import RunEngine
prjemian marked this conversation as resolved.
Show resolved Hide resolved

fallback = None
for fr in inspect.stack(): # Walk backwards from this frame.
static = fr.frame.f_locals.copy() # f_locals will change during 'for'.
for k, v in static.items():
if isinstance(v, RunEngine): # Got one!
if k == "RE":
return v # Ideal selection.
fallback = fallback or None
return fallback


def newSpecFile(title, scan_id=None, RE=None):
"""
User choice of the SPEC file name.
Expand All @@ -59,6 +85,7 @@ def newSpecFile(title, scan_id=None, RE=None):
``RE.md["scan_id"]`` is set to the last scan number in the file.
"""
kwargs = {}
RE = RE or RE_finder() # Search for a defined RunEngine instance
if RE is not None:
kwargs["RE"] = RE

Expand Down
38 changes: 36 additions & 2 deletions bluesky/tests/test_newSpecFile.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@

import pytest
from apstools.utils import cleanupText
from instrument.callbacks.spec_data_file_writer import newSpecFile, specwriter
from spec2nexus.spec import SpecDataFile, is_spec_file
from spec2nexus.spec import SpecDataFile
from spec2nexus.spec import is_spec_file

from bluesky.run_engine import RunEngine
from instrument.callbacks.spec_data_file_writer import RE_finder
from instrument.callbacks.spec_data_file_writer import newSpecFile
from instrument.callbacks.spec_data_file_writer import specwriter

INITIAL_SCAN_ID = 1234
RE = RunEngine(dict(scan_id=INITIAL_SCAN_ID))
Expand Down Expand Up @@ -61,6 +64,37 @@ def test_newSpecFile(title, scan_id, tempdir):
assert isinstance(specwriter.spec_filename, pathlib.Path)


@pytest.mark.parametrize("scan_id", [1, 2, 3, INITIAL_SCAN_ID - 1, INITIAL_SCAN_ID + 1])
def test_issue_271(scan_id, tempdir):
"""newSpecFile("title", scan_id=1) did not reset scan id."""
found_RE = RE_finder() # Won't find the one in this module's globals()
assert found_RE is None

RE = RunEngine() # define for this function, so it can be found
found_RE = RE_finder()
assert found_RE is not None
assert found_RE == RE

assert isinstance(scan_id, int)
assert tempdir.exists()
os.chdir(tempdir) # newSpecFile() works in pwd

RE.md["scan_id"] = INITIAL_SCAN_ID
assert RE.md["scan_id"] == INITIAL_SCAN_ID

newSpecFile("title", scan_id=scan_id, RE=RE)
assert RE.md["scan_id"] != INITIAL_SCAN_ID
assert RE.md["scan_id"] == scan_id

# repeat, without passing RE as parameter
RE.md["scan_id"] = INITIAL_SCAN_ID
assert RE.md["scan_id"] == INITIAL_SCAN_ID

newSpecFile("title", scan_id=scan_id)
assert RE.md["scan_id"] != INITIAL_SCAN_ID
assert RE.md["scan_id"] == scan_id


Comment on lines +68 to +97
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good testing!

def test_newSpecFile_with_existing(tempdir):
assert tempdir.exists()
os.chdir(tempdir) # newSpecFile() works in pwd
Expand Down