From 77cbea486fb8a1992381e45a9a5e28ba909fcb2c Mon Sep 17 00:00:00 2001 From: David Perl Date: Wed, 17 Apr 2024 11:33:09 +0100 Subject: [PATCH 01/10] (Bluesky #1682) add OpenTelemetry tracing to status - Adds opentelemetry-api as a dependency - Registers traces on __init__ of Status objects, ending when they are marked done - Registers traces on Status.wait() --- docs/conf.py | 2 +- ophyd/status.py | 27 ++++++++++++++++++++++++--- setup.cfg | 2 ++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 5df84c2d4..9d98e2146 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -104,7 +104,7 @@ # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = { "python": ("https://docs.python.org/3", None), - "bluesky": ("https://blueskyproject.io/bluesky/", None), + "bluesky": ("https://blueskyproject.io/bluesky/main", None), "numpy": ("https://numpy.org/devdocs/", None), "databroker": ("https://blueskyproject.io/databroker/", None), "event-model": ("https://blueskyproject.io/event-model/main", None), diff --git a/ophyd/status.py b/ophyd/status.py index 436de87d2..73b6804d4 100644 --- a/ophyd/status.py +++ b/ophyd/status.py @@ -6,6 +6,7 @@ from warnings import warn import numpy as np +from opentelemetry import trace from .log import logger from .utils import ( @@ -16,6 +17,8 @@ adapt_old_callback_signature, ) +tracer = trace.get_tracer(__name__) + class UseNewProperty(RuntimeError): ... @@ -80,6 +83,7 @@ class StatusBase: def __init__(self, *, timeout=None, settle_time=0, done=None, success=None): super().__init__() + self._tracing_span = tracer.start_span("ophyd status") self._tname = None self._lock = threading.RLock() self._event = threading.Event() # state associated with done-ness @@ -134,6 +138,9 @@ def __init__(self, *, timeout=None, settle_time=0, done=None, success=None): ) self.set_exception(exc) + self._tracing_span.set_attribute("type", self.__class__.__name__) + self._tracing_span.set_attribute("object_repr", repr(self)) + @property def timeout(self): """ @@ -278,6 +285,7 @@ def _run_callbacks(self): self, ) self._callbacks.clear() + self._tracing_span.end() def set_exception(self, exc): """ @@ -329,6 +337,7 @@ def set_exception(self, exc): self._exception = exc self._settled_event.set() + self._tracing_span.end() if self._callback_thread is None: self._run_callbacks() @@ -349,6 +358,7 @@ def set_finished(self): # Note that in either case, the callbacks themselves are run from the # same thread. This just sets an Event, either from this thread (the # one calling set_finished) or the thread created below. + self._tracing_span.end() if self.settle_time > 0: if self._callback_thread is None: @@ -420,6 +430,7 @@ def exception(self, timeout=None): raise WaitTimeoutError(f"Status {self!r} has not completed yet.") return self._exception + @tracer.start_as_current_span("ophyd status wait") def wait(self, timeout=None): """ Block until the action completes. @@ -446,6 +457,7 @@ def wait(self, timeout=None): indicates that the action itself raised ``TimeoutError``, distinct from ``WaitTimeoutError`` above. """ + trace.get_current_span().set_attribute("object_repr", repr(self)) if not self._event.wait(timeout=timeout): raise WaitTimeoutError(f"Status {self!r} has not completed yet.") if self._exception is not None: @@ -546,9 +558,11 @@ class AndStatus(StatusBase): "a Status that has composes two other Status objects using logical and" def __init__(self, left, right, **kwargs): - super().__init__(**kwargs) self.left = left self.right = right + super().__init__(**kwargs) + self._tracing_span.set_attribute("left", repr(self.left)) + self._tracing_span.set_attribute("right", repr(self.right)) def inner(status): with self._lock: @@ -628,6 +642,11 @@ def __init__(self, obj=None, timeout=None, settle_time=0, done=None, success=Non super().__init__( timeout=timeout, settle_time=settle_time, done=done, success=success ) + ( + self._tracing_span.set_attribute("obj", obj) + if obj + else self._tracing_span.set_attribute("no_obj_given", True) + ) def __str__(self): return ( @@ -664,6 +683,7 @@ def __init__(self, device, **kwargs): self.device = device self._watchers = [] super().__init__(**kwargs) + self._tracing_span.set_attribute("device", repr(self.device)) def _handle_failure(self): super()._handle_failure() @@ -671,10 +691,11 @@ def _handle_failure(self): self.device.stop() def __str__(self): + device_name = self.device.name if self.device else "None" return ( - "{0}(device={1.device.name}, done={1.done}, " + "{0}(device={2}, done={1.done}, " "success={1.success})" - "".format(self.__class__.__name__, self) + "".format(self.__class__.__name__, self, device_name) ) def watch(self, func): diff --git a/setup.cfg b/setup.cfg index 5c99ccd28..4a394ac5e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -21,6 +21,7 @@ setup_requires = install_requires = networkx>=2.0 numpy + opentelemetry-api packaging pint @@ -63,6 +64,7 @@ dev = pytest-rerunfailures pytest-timeout pipdeptree + setuptools>=64 setuptools_scm[toml]>=6.2 sphinx-autobuild sphinx-design From 18e9a5d27a22bd1a90a0912e3db9bd43d91a2c11 Mon Sep 17 00:00:00 2001 From: David Perl Date: Mon, 10 Jun 2024 12:59:12 +0100 Subject: [PATCH 02/10] improve handling of trace attributes and rely less on repr --- ophyd/status.py | 67 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/ophyd/status.py b/ophyd/status.py index 73b6804d4..3a65dab54 100644 --- a/ophyd/status.py +++ b/ophyd/status.py @@ -18,7 +18,7 @@ ) tracer = trace.get_tracer(__name__) - +_TRACE_PREFIX = "Ophyd Status" class UseNewProperty(RuntimeError): ... @@ -83,7 +83,7 @@ class StatusBase: def __init__(self, *, timeout=None, settle_time=0, done=None, success=None): super().__init__() - self._tracing_span = tracer.start_span("ophyd status") + self._tracing_span = tracer.start_span(_TRACE_PREFIX) self._tname = None self._lock = threading.RLock() self._event = threading.Event() # state associated with done-ness @@ -138,8 +138,12 @@ def __init__(self, *, timeout=None, settle_time=0, done=None, success=None): ) self.set_exception(exc) - self._tracing_span.set_attribute("type", self.__class__.__name__) - self._tracing_span.set_attribute("object_repr", repr(self)) + self._trace_attributes = { + "status_type": self.__class__.__name__, + "object_repr": repr(self), + "timeout": self._timeout, + "settle_time": self._settle_time + } @property def timeout(self): @@ -285,7 +289,7 @@ def _run_callbacks(self): self, ) self._callbacks.clear() - self._tracing_span.end() + self._close_trace() def set_exception(self, exc): """ @@ -298,6 +302,7 @@ def set_exception(self, exc): ---------- exc: Exception """ + self._trace_attributes["exception"] = exc # Since we rely on this being raise-able later, check proactively to # avoid potentially very confusing failures. if not ( @@ -337,7 +342,7 @@ def set_exception(self, exc): self._exception = exc self._settled_event.set() - self._tracing_span.end() + self._close_trace() if self._callback_thread is None: self._run_callbacks() @@ -358,7 +363,7 @@ def set_finished(self): # Note that in either case, the callbacks themselves are run from the # same thread. This just sets an Event, either from this thread (the # one calling set_finished) or the thread created below. - self._tracing_span.end() + self._close_trace() if self.settle_time > 0: if self._callback_thread is None: @@ -430,7 +435,7 @@ def exception(self, timeout=None): raise WaitTimeoutError(f"Status {self!r} has not completed yet.") return self._exception - @tracer.start_as_current_span("ophyd status wait") + @tracer.start_as_current_span(f"{_TRACE_PREFIX} wait") def wait(self, timeout=None): """ Block until the action completes. @@ -457,7 +462,7 @@ def wait(self, timeout=None): indicates that the action itself raised ``TimeoutError``, distinct from ``WaitTimeoutError`` above. """ - trace.get_current_span().set_attribute("object_repr", repr(self)) + _set_trace_attributes(trace.get_current_span(), self._trace_attributes) if not self._event.wait(timeout=timeout): raise WaitTimeoutError(f"Status {self!r} has not completed yet.") if self._exception is not None: @@ -544,6 +549,14 @@ def finished_cb(self, cb): "method instead." ) + + def _update_trace_attributes(self): + _set_trace_attributes(self._tracing_span, self._trace_attributes) + + def _close_trace(self): + self._update_trace_attributes() + self._tracing_span.end() + def __and__(self, other): """ Returns a new 'composite' status object, AndStatus, @@ -561,9 +574,8 @@ def __init__(self, left, right, **kwargs): self.left = left self.right = right super().__init__(**kwargs) - self._tracing_span.set_attribute("left", repr(self.left)) - self._tracing_span.set_attribute("right", repr(self.right)) - + self._trace_attributes["left"] = self.left._trace_attributes + self._trace_attributes["right"] = self.right._trace_attributes def inner(status): with self._lock: if self._externally_initiated_completion: @@ -642,11 +654,8 @@ def __init__(self, obj=None, timeout=None, settle_time=0, done=None, success=Non super().__init__( timeout=timeout, settle_time=settle_time, done=done, success=success ) - ( - self._tracing_span.set_attribute("obj", obj) - if obj - else self._tracing_span.set_attribute("no_obj_given", True) - ) + self._trace_attributes["obj"] = obj + self._trace_attributes["no_obj_given"] = not bool(obj) def __str__(self): return ( @@ -683,7 +692,11 @@ def __init__(self, device, **kwargs): self.device = device self._watchers = [] super().__init__(**kwargs) - self._tracing_span.set_attribute("device", repr(self.device)) + self._trace_attributes["device"] = ( + {"name": device.name, "type": device.__class__.__name__} + if device else "None" + ) + self._trace_attributes["kwargs"] = kwargs def _handle_failure(self): super()._handle_failure() @@ -867,7 +880,7 @@ def check_value(self, *args, **kwargs): try: success = self.callback(*args, **kwargs) - # If successfull start a timer for completion + # If successful start a timer for completion if success: if not self._stable_timer.is_alive(): self._stable_timer.start() @@ -969,6 +982,15 @@ def __init__(self, positioner, target, *, start_ts=None, **kwargs): if not self.done: self.pos.subscribe(self._notify_watchers, event_type=self.pos.SUB_READBACK) + self._trace_attributes.update({ + "positioner" : self.pos, + "target" : target, + "start_time" : start_ts, + "start_pos ": self.pos.position, + "unit": self._unit, + "positioner_name": self._name + }) + def watch(self, func): """ Subscribe to notifications about partial progress. @@ -1044,6 +1066,10 @@ def _settled(self): self._watchers.clear() self.finish_ts = time.time() self.finish_pos = self.pos.position + self._trace_attributes.update({ + "finish_time" : self.finish_ts, + "finish_pos" : self.finish_pos, + }) @property def elapsed(self): @@ -1063,6 +1089,9 @@ def __str__(self): __repr__ = __str__ +def _set_trace_attributes(span, trace_attributes): + for k, v in trace_attributes.items(): + span.set_attribute(k, v) def wait(status, timeout=None, *, poll_rate="DEPRECATED"): """(Blocking) wait for the status object to complete From a3d3b9e38f5410a0fcc9ce8de70d237183f65585 Mon Sep 17 00:00:00 2001 From: David Perl Date: Mon, 10 Jun 2024 13:14:19 +0100 Subject: [PATCH 03/10] format --- ophyd/status.py | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/ophyd/status.py b/ophyd/status.py index 3a65dab54..2f5131c42 100644 --- a/ophyd/status.py +++ b/ophyd/status.py @@ -20,8 +20,8 @@ tracer = trace.get_tracer(__name__) _TRACE_PREFIX = "Ophyd Status" -class UseNewProperty(RuntimeError): - ... + +class UseNewProperty(RuntimeError): ... class StatusBase: @@ -142,7 +142,7 @@ def __init__(self, *, timeout=None, settle_time=0, done=None, success=None): "status_type": self.__class__.__name__, "object_repr": repr(self), "timeout": self._timeout, - "settle_time": self._settle_time + "settle_time": self._settle_time, } @property @@ -549,7 +549,6 @@ def finished_cb(self, cb): "method instead." ) - def _update_trace_attributes(self): _set_trace_attributes(self._tracing_span, self._trace_attributes) @@ -576,6 +575,7 @@ def __init__(self, left, right, **kwargs): super().__init__(**kwargs) self._trace_attributes["left"] = self.left._trace_attributes self._trace_attributes["right"] = self.right._trace_attributes + def inner(status): with self._lock: if self._externally_initiated_completion: @@ -694,7 +694,8 @@ def __init__(self, device, **kwargs): super().__init__(**kwargs) self._trace_attributes["device"] = ( {"name": device.name, "type": device.__class__.__name__} - if device else "None" + if device + else "None" ) self._trace_attributes["kwargs"] = kwargs @@ -982,14 +983,16 @@ def __init__(self, positioner, target, *, start_ts=None, **kwargs): if not self.done: self.pos.subscribe(self._notify_watchers, event_type=self.pos.SUB_READBACK) - self._trace_attributes.update({ - "positioner" : self.pos, - "target" : target, - "start_time" : start_ts, - "start_pos ": self.pos.position, - "unit": self._unit, - "positioner_name": self._name - }) + self._trace_attributes.update( + { + "positioner": self.pos, + "target": target, + "start_time": start_ts, + "start_pos ": self.pos.position, + "unit": self._unit, + "positioner_name": self._name, + } + ) def watch(self, func): """ @@ -1066,10 +1069,12 @@ def _settled(self): self._watchers.clear() self.finish_ts = time.time() self.finish_pos = self.pos.position - self._trace_attributes.update({ - "finish_time" : self.finish_ts, - "finish_pos" : self.finish_pos, - }) + self._trace_attributes.update( + { + "finish_time": self.finish_ts, + "finish_pos": self.finish_pos, + } + ) @property def elapsed(self): @@ -1089,10 +1094,12 @@ def __str__(self): __repr__ = __str__ + def _set_trace_attributes(span, trace_attributes): for k, v in trace_attributes.items(): span.set_attribute(k, v) + def wait(status, timeout=None, *, poll_rate="DEPRECATED"): """(Blocking) wait for the status object to complete From 0ef09656f43cfc0afc56dc6c29007a858b6fa0aa Mon Sep 17 00:00:00 2001 From: David Perl Date: Mon, 10 Jun 2024 13:31:32 +0100 Subject: [PATCH 04/10] fix errors --- ophyd/status.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ophyd/status.py b/ophyd/status.py index 2f5131c42..6049c3377 100644 --- a/ophyd/status.py +++ b/ophyd/status.py @@ -84,6 +84,11 @@ class StatusBase: def __init__(self, *, timeout=None, settle_time=0, done=None, success=None): super().__init__() self._tracing_span = tracer.start_span(_TRACE_PREFIX) + self._trace_attributes = { + "status_type": self.__class__.__name__, + "timeout": timeout, + "settle_time": settle_time, + } self._tname = None self._lock = threading.RLock() self._event = threading.Event() # state associated with done-ness @@ -138,12 +143,7 @@ def __init__(self, *, timeout=None, settle_time=0, done=None, success=None): ) self.set_exception(exc) - self._trace_attributes = { - "status_type": self.__class__.__name__, - "object_repr": repr(self), - "timeout": self._timeout, - "settle_time": self._settle_time, - } + self._trace_attributes["object_repr"] = (repr(self),) @property def timeout(self): From b9d74ca56ab5088bf0eb1c09787b1ed23b6e0bc0 Mon Sep 17 00:00:00 2001 From: David Perl Date: Mon, 10 Jun 2024 13:44:58 +0100 Subject: [PATCH 05/10] fix linting --- ophyd/status.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ophyd/status.py b/ophyd/status.py index 6049c3377..4fc27c1a1 100644 --- a/ophyd/status.py +++ b/ophyd/status.py @@ -21,7 +21,8 @@ _TRACE_PREFIX = "Ophyd Status" -class UseNewProperty(RuntimeError): ... +class UseNewProperty(RuntimeError): + ... class StatusBase: @@ -143,7 +144,7 @@ def __init__(self, *, timeout=None, settle_time=0, done=None, success=None): ) self.set_exception(exc) - self._trace_attributes["object_repr"] = (repr(self),) + self._trace_attributes["object_repr"] = repr(self) @property def timeout(self): From f3e88ee89000aee1d0b11229ec38297dc03ac4f9 Mon Sep 17 00:00:00 2001 From: David Perl Date: Tue, 18 Jun 2024 09:42:29 +0100 Subject: [PATCH 06/10] fix data types --- ophyd/status.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/ophyd/status.py b/ophyd/status.py index 4fc27c1a1..9e50675db 100644 --- a/ophyd/status.py +++ b/ophyd/status.py @@ -1,3 +1,4 @@ +import json import threading import time from collections import deque @@ -87,9 +88,9 @@ def __init__(self, *, timeout=None, settle_time=0, done=None, success=None): self._tracing_span = tracer.start_span(_TRACE_PREFIX) self._trace_attributes = { "status_type": self.__class__.__name__, - "timeout": timeout, "settle_time": settle_time, } + self._trace_attributes.update({"timeout": timeout} if timeout else {"no_timeout_given": True}) self._tname = None self._lock = threading.RLock() self._event = threading.Event() # state associated with done-ness @@ -290,7 +291,6 @@ def _run_callbacks(self): self, ) self._callbacks.clear() - self._close_trace() def set_exception(self, exc): """ @@ -364,7 +364,6 @@ def set_finished(self): # Note that in either case, the callbacks themselves are run from the # same thread. This just sets an Event, either from this thread (the # one calling set_finished) or the thread created below. - self._close_trace() if self.settle_time > 0: if self._callback_thread is None: @@ -380,6 +379,8 @@ def settle_done(): if self._callback_thread is None: self._run_callbacks() + self._close_trace() + def _finished(self, success=True, **kwargs): """ @@ -693,12 +694,12 @@ def __init__(self, device, **kwargs): self.device = device self._watchers = [] super().__init__(**kwargs) - self._trace_attributes["device"] = ( - {"name": device.name, "type": device.__class__.__name__} + self._trace_attributes.update( + {"device_name": device.name, "device_type": device.__class__.__name__} if device - else "None" + else {"no_device_given" : True} ) - self._trace_attributes["kwargs"] = kwargs + self._trace_attributes["kwargs"] = json.dumps(kwargs) def _handle_failure(self): super()._handle_failure() @@ -986,7 +987,6 @@ def __init__(self, positioner, target, *, start_ts=None, **kwargs): self._trace_attributes.update( { - "positioner": self.pos, "target": target, "start_time": start_ts, "start_pos ": self.pos.position, @@ -994,6 +994,8 @@ def __init__(self, positioner, target, *, start_ts=None, **kwargs): "positioner_name": self._name, } ) + self._trace_attributes.update( {"positioner": repr(self.pos)} if self.pos else {"no_positioner_given":True} +) def watch(self, func): """ From 71b5ef9877a2ff565b701782d256eba1314249ea Mon Sep 17 00:00:00 2001 From: David Perl Date: Tue, 18 Jun 2024 09:53:10 +0100 Subject: [PATCH 07/10] add doc and improve formatting --- docs/user/explanations/otel-tracing | 4 ++++ ophyd/status.py | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 docs/user/explanations/otel-tracing diff --git a/docs/user/explanations/otel-tracing b/docs/user/explanations/otel-tracing new file mode 100644 index 000000000..25328fb56 --- /dev/null +++ b/docs/user/explanations/otel-tracing @@ -0,0 +1,4 @@ +Tracing with Opentelemetry +========================== + +Ophyd is instrumented with [OpenTelemetry](https://opentelemetry.io/) tracing span hooks on the lifetime of `Status` objects and their `.wait()` method. Please see the [Bluesky documentation](https://blueskyproject.io/bluesky/main/otel_tracing.html) for examples of how to make use of this. \ No newline at end of file diff --git a/ophyd/status.py b/ophyd/status.py index 9e50675db..768aaaca5 100644 --- a/ophyd/status.py +++ b/ophyd/status.py @@ -381,7 +381,6 @@ def settle_done(): self._run_callbacks() self._close_trace() - def _finished(self, success=True, **kwargs): """ Inform the status object that it is done and if it succeeded. @@ -994,8 +993,9 @@ def __init__(self, positioner, target, *, start_ts=None, **kwargs): "positioner_name": self._name, } ) - self._trace_attributes.update( {"positioner": repr(self.pos)} if self.pos else {"no_positioner_given":True} -) + self._trace_attributes.update( + {"positioner": repr(self.pos)} if self.pos else {"no_positioner_given": True} + ) def watch(self, func): """ From 5c7416ee15ba02769a3a7731462306895431a2d9 Mon Sep 17 00:00:00 2001 From: David Perl Date: Tue, 18 Jun 2024 11:23:14 +0100 Subject: [PATCH 08/10] fix linting --- ophyd/status.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ophyd/status.py b/ophyd/status.py index 768aaaca5..8639ba48e 100644 --- a/ophyd/status.py +++ b/ophyd/status.py @@ -90,7 +90,9 @@ def __init__(self, *, timeout=None, settle_time=0, done=None, success=None): "status_type": self.__class__.__name__, "settle_time": settle_time, } - self._trace_attributes.update({"timeout": timeout} if timeout else {"no_timeout_given": True}) + self._trace_attributes.update( + {"timeout": timeout} if timeout else {"no_timeout_given": True} + ) self._tname = None self._lock = threading.RLock() self._event = threading.Event() # state associated with done-ness @@ -696,7 +698,7 @@ def __init__(self, device, **kwargs): self._trace_attributes.update( {"device_name": device.name, "device_type": device.__class__.__name__} if device - else {"no_device_given" : True} + else {"no_device_given": True} ) self._trace_attributes["kwargs"] = json.dumps(kwargs) @@ -994,7 +996,9 @@ def __init__(self, positioner, target, *, start_ts=None, **kwargs): } ) self._trace_attributes.update( - {"positioner": repr(self.pos)} if self.pos else {"no_positioner_given": True} + {"positioner": repr(self.pos)} + if self.pos + else {"no_positioner_given": True} ) def watch(self, func): From f1a16f96ca8896e09a476f1d842eb9e435811a64 Mon Sep 17 00:00:00 2001 From: David Perl Date: Tue, 18 Jun 2024 11:27:17 +0100 Subject: [PATCH 09/10] make json more robust --- ophyd/status.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ophyd/status.py b/ophyd/status.py index 8639ba48e..428eb47cb 100644 --- a/ophyd/status.py +++ b/ophyd/status.py @@ -700,7 +700,7 @@ def __init__(self, device, **kwargs): if device else {"no_device_given": True} ) - self._trace_attributes["kwargs"] = json.dumps(kwargs) + self._trace_attributes["kwargs"] = json.dumps(kwargs, default=repr) def _handle_failure(self): super()._handle_failure() From b38c06269698e997fb94b5654f2bc4662ca6a5be Mon Sep 17 00:00:00 2001 From: David Perl Date: Wed, 3 Jul 2024 15:21:40 +0100 Subject: [PATCH 10/10] override docker version deprecation --- scripts/docker.conf | 2 ++ scripts/epics_docker.sh | 8 ++++++++ setup.cfg | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 scripts/docker.conf diff --git a/scripts/docker.conf b/scripts/docker.conf new file mode 100644 index 000000000..ae284beff --- /dev/null +++ b/scripts/docker.conf @@ -0,0 +1,2 @@ +[Service] +Environment="DOCKER_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE=1" \ No newline at end of file diff --git a/scripts/epics_docker.sh b/scripts/epics_docker.sh index aa96c12b8..405c19fb7 100755 --- a/scripts/epics_docker.sh +++ b/scripts/epics_docker.sh @@ -3,6 +3,14 @@ SCRIPTS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" source $SCRIPTS_DIR/epics_exports.sh +# Override the deprecation warning of V1 images +# Remove when images are updated +sudo mkdir -p /etc/systemd/system/docker.service.d +file="/etc/systemd/system/docker.service.d/extra_env.conf" +sudo cp $SCRIPTS_DIR/docker.conf $file +sudo systemctl daemon-reload +sudo systemctl restart docker + MOTOR_DOCKERIMAGE="nsls2/epics-docker:latest" PE_DOCKERIMAGE="nsls2/pyepics-docker:latest" AD_DOCKERIMAGE="prjemian/synapps-6.1-ad-3.7:latest" diff --git a/setup.cfg b/setup.cfg index 4a394ac5e..158f76418 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,7 +20,7 @@ setup_requires = # Specify any package dependencies below. install_requires = networkx>=2.0 - numpy + numpy<2.0 opentelemetry-api packaging pint