pyobs-core 2.0.0.dev26__tar.gz → 2.0.0.dev28__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/PKG-INFO +1 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/comm/xmpp/rpc.py +56 -24
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/comm/xmpp/xmppcomm.py +3 -3
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IAcquisition.py +4 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IAutoFocus.py +2 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/ICalibrate.py +5 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IConfig.py +3 -2
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IData.py +1 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IDataSequence.py +2 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IExposureTime.py +2 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IFilters.py +1 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IFlatField.py +3 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IFocusModel.py +7 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IFocuser.py +3 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IMode.py +1 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IMultiFiber.py +3 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IPointingAltAz.py +2 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IPointingBody.py +5 -2
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IPointingHeliocentricPolar.py +3 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IPointingHeliographicStonyhurst.py +3 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IPointingHelioprojective.py +3 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IPointingOrbitalElements.py +6 -3
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IPointingRaDec.py +3 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IPointingSeries.py +5 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IRotation.py +5 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IRunnable.py +7 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IScriptRunner.py +3 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/ISyncTarget.py +5 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/ITrackingMode.py +1 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IWeather.py +4 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/camera/basecamera.py +12 -13
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/camera/basespectrograph.py +8 -2
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/camera/basevideo.py +5 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/camera/dummycamera.py +2 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/camera/dummyspectrograph.py +3 -2
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/flatfield/flatfield.py +7 -7
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/flatfield/scheduler.py +7 -2
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/focus/focusmodel.py +39 -6
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/focus/focusseries.py +5 -5
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/module.py +188 -35
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/pointing/_base.py +2 -2
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/pointing/guidingstatistics/pixeloffset.py +2 -2
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/pointing/guidingstatistics/skyoffsets.py +1 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/pointing/guidingstatistics/uptime.py +1 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/pointing/scienceframeguiding.py +5 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/robotic/mastermind.py +7 -2
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/robotic/scriptrunner.py +13 -3
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/roof/basedome.py +1 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/roof/dummyroof.py +20 -13
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/telescope/_dummytelescopebase.py +44 -18
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/telescope/basetelescope.py +53 -14
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/utils/dummymode.py +3 -2
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/weather/mockweather.py +5 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/weather/weather.py +13 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/astroplanscheduler.py +3 -1
- pyobs_core-2.0.0.dev28/pyobs/robotic/scripts/__init__.py +4 -0
- pyobs_core-2.0.0.dev28/pyobs/robotic/scripts/exceptions.py +12 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scripts/imaging/autofocus.py +6 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scripts/imaging/imaging.py +1 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/lco/task.py +11 -11
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/lco/taskrunner.py +7 -4
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/task.py +7 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/taskrunner.py +9 -5
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/curvefit.py +13 -1
- pyobs_core-2.0.0.dev28/pyobs/utils/exceptions.py +195 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/focusseries/photometry.py +6 -1
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/focusseries/projection.py +9 -8
- pyobs_core-2.0.0.dev28/pyobs/utils/threads/__init__.py +3 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/threads/lockwithabort.py +4 -7
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyproject.toml +1 -1
- pyobs_core-2.0.0.dev26/pyobs/robotic/scripts/__init__.py +0 -3
- pyobs_core-2.0.0.dev26/pyobs/utils/exceptions.py +0 -290
- pyobs_core-2.0.0.dev26/pyobs/utils/threads/__init__.py +0 -3
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/.gitignore +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/LICENSE +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/application.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/background_task.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/cli/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/cli/_cli.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/cli/pyobs.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/cli/pyobsd.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/cli/pyobsw.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/comm/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/comm/comm.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/comm/commlogging.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/comm/dummy/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/comm/dummy/dummycomm.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/comm/local/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/comm/local/localcomm.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/comm/local/localnetwork.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/comm/proxy.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/comm/xmpp/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/comm/xmpp/serializer.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/comm/xmpp/xep_0009/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/comm/xmpp/xep_0009/binding.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/comm/xmpp/xep_0009/rpc.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/comm/xmpp/xep_0009_timeout/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/comm/xmpp/xep_0009_timeout/rpc.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/comm/xmpp/xep_0009_timeout/stanza/RPC.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/comm/xmpp/xep_0009_timeout/stanza/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/comm/xmpp/xmppclient.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/events/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/events/badweather.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/events/event.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/events/exposurestatuschanged.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/events/filterchanged.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/events/focusfound.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/events/goodweather.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/events/log.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/events/modechanged.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/events/moduleclosed.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/events/moduleopened.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/events/motionstatuschanged.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/events/move.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/events/newimage.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/events/newspectrum.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/events/offsets.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/events/roofclosing.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/events/roofopened.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/events/taskfailed.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/events/taskfinished.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/events/taskstarted.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/events/testevent.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/image.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/meta/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/meta/altazoffsets.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/meta/exptime.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/meta/genericoffset.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/meta/onskydistance.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/meta/pixeloffsets.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/meta/radecoffsets.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/meta/skyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processor.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/_daobackgroundremover.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/annotation/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/annotation/_pillow.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/annotation/circle.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/annotation/crosshair.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/annotation/text.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/astrometry/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/astrometry/_dotnet_request.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/astrometry/_dotnet_request_builder.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/astrometry/_dotnet_request_logger.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/astrometry/_dotnet_response_saver.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/astrometry/astrometry.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/astrometry/dotnet.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/calibration/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/calibration/_calibration_cache.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/calibration/_ccddata_calibrator.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/calibration/calibration.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/detection/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/detection/_pysep_stats_calculator.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/detection/_source_catalog.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/detection/daophot.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/detection/pysep.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/detection/simpledisk.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/detection/sourcedetection.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/exptime/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/exptime/exptime.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/exptime/star.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/image/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/image/addfitsheaders.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/image/download.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/image/flip.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/image/grayscale.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/image/httpserver.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/image/normalize.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/image/save.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/image/saveimage.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/image/smooth.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/image/softbin.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/misc/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/misc/addmask.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/misc/catalogcircularmask.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/misc/circularmask.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/misc/createfilename.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/misc/imagesourcefilter.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/misc/removebackground.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/modules/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/modules/getfitsheaders.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/offsets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/offsets/astrometry.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/offsets/brighteststar.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/offsets/brighteststar_guiding.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/offsets/dummyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/offsets/dummyskyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/offsets/fitsheader.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/offsets/offsets.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/offsets/pixeloffsets.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/offsets/projected.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/offsets/spilled_light.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/photometry/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/photometry/_photometry_calculator.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/photometry/_photutil_aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/photometry/_sep_aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/photometry/aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/photometry/photometry.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/photometry/photutil.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/photometry/pysep.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/wcs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/images/processors/wcs/solarhelioprojective.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IAbortable.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IAutoGuiding.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IAutonomous.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IBinning.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/ICamera.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/ICooling.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IDome.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IExposure.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IFitsHeaderAfter.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IFitsHeaderBefore.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IGain.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IImageFormat.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IImageType.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IModule.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IMotion.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IOffsetsAltAz.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IOffsetsRaDec.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IReady.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IRoof.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IRunning.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/ISpectrograph.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IStartStop.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IStructuredConfig.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/ITelescope.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/ITemperatures.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/ITrackingRate.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IVideo.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IWindow.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/interface.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/mixins/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/mixins/camerasettings.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/mixins/fitsheader.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/mixins/fitsnamespace.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/mixins/follow.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/mixins/motionstatus.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/mixins/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/mixins/waitformotion.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/mixins/weatheraware.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/camera/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/camera/adaptive.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/camera/dummyvideo.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/camera/pipelinecamera.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/flatfield/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/flatfield/pointing.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/focus/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/focus/dummyautofocus.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/image/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/image/imagewatcher.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/image/imagewriter.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/image/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/image/seeing.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/pointing/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/pointing/_baseguiding.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/pointing/acquisition.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/pointing/autoguiding.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/pointing/dummyacquisition.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/pointing/dummyguiding.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/pointing/guidingstatistics/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/pointing/guidingstatistics/guidingstatistics.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/robotic/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/robotic/pointing.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/robotic/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/roof/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/roof/baseroof.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/telescope/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/telescope/dummyaltaztelescope.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/telescope/dummyradectelescope.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/telescope/dummysolartelescope.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/test/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/test/standalone.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/utils/fluentlogger.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/utils/httpfilecache.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/utils/kiosk.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/utils/matrix.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/utils/stellarium.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/utils/telegram.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/utils/trigger.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/weather/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/weather/weather_api.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/modules/weather/weather_state.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/object.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/py.typed +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/observation.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/constraints/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/constraints/airmassconstraint.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/constraints/constraint.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/constraints/moonilluminationconstraint.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/constraints/moonseparationconstraint.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/constraints/solarelevationconstraint.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/constraints/timeconstraint.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/dataprovider.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/merits/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/merits/aftertime.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/merits/beforetime.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/merits/constant.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/merits/follow.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/merits/interval.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/merits/merit.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/merits/pernight.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/merits/random.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/merits/timewindow.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/merits/transit.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/observationarchiveevolution.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/ondemandscheduler.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/targets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/targets/dynamictarget.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/targets/heliocentricpolartarget.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/targets/helioprojectivetarget.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/targets/picker/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/targets/picker/csvpicker.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/targets/picker/picker.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/targets/siderealtarget.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/targets/target.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scheduler/taskscheduler.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scripts/calibration/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scripts/calibration/darkbias.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scripts/calibration/pointing.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scripts/calibration/skyflats.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scripts/control/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scripts/control/cases.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scripts/control/conditional.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scripts/control/parallel.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scripts/control/selector.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scripts/control/sequential.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scripts/imaging/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scripts/imaging/transitimaging.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scripts/script.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scripts/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scripts/utils/callmodule.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scripts/utils/debugtrigger.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/scripts/utils/log.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/backend/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/backend/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/backend/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/filesystem/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/filesystem/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/filesystem/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/lco/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/lco/_portal.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/lco/_schedulereader.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/lco/_schedulewriter.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/lco/configdb.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/lco/mockobservationarchive.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/lco/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/lco/scripts/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/lco/scripts/autofocus.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/lco/scripts/default.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/lco/scripts/script.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/lco/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/memory/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/memory/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/memory/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/storage/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/utils/archive/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/utils/archive/archive.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/utils/archive/local_archive.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/utils/archive/pyobs_archive.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/utils/exptime/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/utils/exptime/exptime.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/utils/exptime/stellarexptime.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/utils/skyflats/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/utils/skyflats/exptimeeval.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/utils/skyflats/flatfielder.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/utils/skyflats/pointing/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/utils/skyflats/pointing/base.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/utils/skyflats/pointing/static.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/utils/skyflats/priorities/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/utils/skyflats/priorities/archive.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/utils/skyflats/priorities/base.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/utils/skyflats/priorities/const.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/robotic/utils/skyflats/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/average.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/cache.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/config.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/config_schema.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/coordinates.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/enums.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/fits.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/focusseries/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/focusseries/base.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/grids/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/grids/filters.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/grids/grid.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/grids/gridnode.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/grids/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/gui/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/gui/camera/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/gui/camera/binningwidget.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/gui/camera/datadisplaywidget.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/gui/camera/exposewidget.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/gui/camera/exposuretimewidget.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/gui/camera/imageformatwidget.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/gui/camera/listpickerdialog.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/gui/camera/windowingwidget.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/http.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/influxdb.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/logger.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/logging/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/logging/context.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/logging/resolvableerror.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/modulegui.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/offsets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/offsets/applyaltazoffsets.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/offsets/applyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/offsets/applyradecoffsets.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/parallel.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/pipeline/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/pipeline/night.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/pipeline/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/publisher/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/publisher/csv.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/publisher/http.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/publisher/log.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/publisher/multi.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/publisher/publisher.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/serialization.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/shellcommand.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/time.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/utils/units.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/version.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/vfs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/vfs/archivefile.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/vfs/bufferedfile.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/vfs/file.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/vfs/filelists/__init__.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/vfs/filelists/filelist.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/vfs/filelists/testing.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/vfs/httpfile.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/vfs/localfile.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/vfs/memfile.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/vfs/sftpfile.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/vfs/smbfile.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/vfs/sshfile.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/vfs/tempfile.py +0 -0
- {pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/vfs/vfs.py +0 -0
|
@@ -96,9 +96,22 @@ def fault_to_xml(exception: Exception) -> ET.Element:
|
|
|
96
96
|
value_elem = ET.Element(f"{{{_NS}}}value")
|
|
97
97
|
pyobs_fault = ET.Element(f"{{{_PYOBS_NS}}}fault")
|
|
98
98
|
exc_elem = ET.Element("exception")
|
|
99
|
-
|
|
99
|
+
# Fully-qualified name, not the bare class name -- domain exceptions can live anywhere, not
|
|
100
|
+
# just in pyobs.utils.exceptions (see PyobsError._registry / resolve()). If this is an
|
|
101
|
+
# UnclassifiedError wrapping something that was never a PyobsError to begin with (see
|
|
102
|
+
# Module.execute()'s classification), serialize the ORIGINAL type's name instead of
|
|
103
|
+
# "UnclassifiedError" itself -- original_type never crosses the wire as an attribute (only the
|
|
104
|
+
# class name and message do), so this is the only way it survives to the caller. The caller's
|
|
105
|
+
# own registry lookup then decides fresh: an unregistered builtin/vendor type still correctly
|
|
106
|
+
# falls back to UnclassifiedError, but this time with original_type actually populated.
|
|
107
|
+
original_type = getattr(exception, "original_type", None)
|
|
108
|
+
exc_elem.text = original_type if original_type else f"{type(exception).__module__}.{type(exception).__qualname__}"
|
|
100
109
|
msg_elem = ET.Element("message")
|
|
101
|
-
|
|
110
|
+
# the raw message, not str(exception) -- str() already prepends "<ClassName>", and
|
|
111
|
+
# reconstruction on the caller's side passes this straight back in as the new instance's
|
|
112
|
+
# message, so serializing str() here would bake in a doubled "<ClassName> <ClassName> ..." once
|
|
113
|
+
# the caller's own __str__ formats it again
|
|
114
|
+
msg_elem.text = getattr(exception, "message", None) or str(exception)
|
|
102
115
|
pyobs_fault.append(exc_elem)
|
|
103
116
|
pyobs_fault.append(msg_elem)
|
|
104
117
|
value_elem.append(pyobs_fault)
|
|
@@ -107,16 +120,17 @@ def fault_to_xml(exception: Exception) -> ET.Element:
|
|
|
107
120
|
|
|
108
121
|
|
|
109
122
|
def xml_to_fault(fault_elem: ET.Element) -> tuple[str, str]:
|
|
110
|
-
"""Parse <fault> and return (
|
|
123
|
+
"""Parse <fault> and return (exception_qualified_name, message)."""
|
|
124
|
+
_fallback_name = f"{exc.RemoteError.__module__}.{exc.RemoteError.__qualname__}"
|
|
111
125
|
value_elem = fault_elem.find(f"{{{_NS}}}value")
|
|
112
126
|
if value_elem is None:
|
|
113
|
-
return
|
|
127
|
+
return _fallback_name, "Unknown error"
|
|
114
128
|
pyobs_fault = value_elem.find(f"{{{_PYOBS_NS}}}fault")
|
|
115
129
|
if pyobs_fault is None:
|
|
116
|
-
return
|
|
130
|
+
return _fallback_name, "Unknown error"
|
|
117
131
|
exc_el = pyobs_fault.find("exception")
|
|
118
132
|
msg_el = pyobs_fault.find("message")
|
|
119
|
-
exc_name = (exc_el.text if exc_el is not None else None) or
|
|
133
|
+
exc_name = (exc_el.text if exc_el is not None else None) or _fallback_name
|
|
120
134
|
msg = (msg_el.text if msg_el is not None else None) or ""
|
|
121
135
|
return exc_name, msg
|
|
122
136
|
|
|
@@ -170,6 +184,13 @@ class RPC:
|
|
|
170
184
|
iq.enable("rpc_query")
|
|
171
185
|
pmethod = iq["rpc_query"]["method_call"]["method_name"]
|
|
172
186
|
|
|
187
|
+
# XEP-0009 already assigns this per call (used elsewhere as the Future dict key) -- reuse
|
|
188
|
+
# it as a correlation id so an operator can jump from a caller-side exception straight to
|
|
189
|
+
# the matching origin-side log line, instead of neither side pointing at the other
|
|
190
|
+
call_id: str | slixmpp.JID = iq["id"]
|
|
191
|
+
if isinstance(call_id, slixmpp.JID):
|
|
192
|
+
call_id = call_id.node
|
|
193
|
+
|
|
173
194
|
try:
|
|
174
195
|
if self._handler is None:
|
|
175
196
|
return
|
|
@@ -208,7 +229,7 @@ class RPC:
|
|
|
208
229
|
response.send()
|
|
209
230
|
|
|
210
231
|
# Call method
|
|
211
|
-
return_value = await self._handler.execute(pmethod, *params, sender=iq["from"].user)
|
|
232
|
+
return_value = await self._handler.execute(pmethod, *params, sender=iq["from"].user, call_id=call_id)
|
|
212
233
|
|
|
213
234
|
# Serialize return value
|
|
214
235
|
return_type = hints.get("return", type(None))
|
|
@@ -220,9 +241,12 @@ class RPC:
|
|
|
220
241
|
self._client.plugin["xep_0009"].forbidden(iq).send()
|
|
221
242
|
|
|
222
243
|
except Exception as e:
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
244
|
+
# Module.execute() already classified and logged anything raised by the call itself
|
|
245
|
+
# (every transport gets the same treatment there now), so there's nothing left to do
|
|
246
|
+
# here but serialize and send the fault -- except for failures that never reached
|
|
247
|
+
# execute() at all (e.g. malformed RPC parameters during deserialization above), which
|
|
248
|
+
# this is the only place that will ever log
|
|
249
|
+
if not isinstance(e, exc.PyobsError):
|
|
226
250
|
log.exception("Unexpected exception in %s.", pmethod)
|
|
227
251
|
self._client.plugin["xep_0009"].send_fault(iq, fault_to_xml(e))
|
|
228
252
|
|
|
@@ -269,18 +293,22 @@ class RPC:
|
|
|
269
293
|
fault_elem = iq["rpc_query"]["method_response"]["fault"]
|
|
270
294
|
exc_name, msg = xml_to_fault(fault_elem)
|
|
271
295
|
|
|
272
|
-
exception_class = getattr(exc, exc_name, None)
|
|
273
|
-
if exception_class is None or not issubclass(exception_class, Exception):
|
|
274
|
-
exception_class = exc.RemoteError
|
|
275
|
-
|
|
276
296
|
sender = iq["from"].node
|
|
277
|
-
|
|
278
|
-
|
|
297
|
+
exception_class = exc.PyobsError.resolve(exc_name)
|
|
298
|
+
if exception_class is not None:
|
|
299
|
+
# real registered type (e.g. FocusError) -- raised as itself, not wrapped
|
|
300
|
+
exception: exc.PyobsError = exception_class(msg, remote_module=sender)
|
|
279
301
|
else:
|
|
280
|
-
|
|
302
|
+
# unresolvable: never a PyobsError to begin with, or its defining module was never
|
|
303
|
+
# imported in this process -- the qualified name string still survives as original_type
|
|
304
|
+
exception = exc.UnclassifiedError(msg, original_type=exc_name, remote_module=sender)
|
|
305
|
+
|
|
306
|
+
# same correlation id Module.execute() logged on the origin side -- an operator can jump
|
|
307
|
+
# straight from this caller-side exception to the matching detailed log line, by id
|
|
308
|
+
setattr(exception, "call_id", jid)
|
|
281
309
|
|
|
282
310
|
if not future.done():
|
|
283
|
-
future.set_exception(
|
|
311
|
+
future.set_exception(exception)
|
|
284
312
|
|
|
285
313
|
async def _on_jabber_rpc_error(self, iq: Any) -> None:
|
|
286
314
|
pmethod = self._client.plugin["xep_0009"].extract_method(iq["rpc_query"])
|
|
@@ -295,12 +323,16 @@ class RPC:
|
|
|
295
323
|
|
|
296
324
|
sender = iq["from"].node
|
|
297
325
|
e = {
|
|
298
|
-
"item-not-found": exc.RemoteError(
|
|
299
|
-
"forbidden": exc.RemoteError(
|
|
300
|
-
"undefined-condition": exc.RemoteError(
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
326
|
+
"item-not-found": exc.RemoteError(f"No remote handler for {pmethod} at {iq['from']}!", module=sender),
|
|
327
|
+
"forbidden": exc.RemoteError(f"Forbidden to invoke {pmethod} at {iq['from']}!", module=sender),
|
|
328
|
+
"undefined-condition": exc.RemoteError(
|
|
329
|
+
f"Unexpected problem invoking {pmethod} at {iq['from']}!", module=sender
|
|
330
|
+
),
|
|
331
|
+
"service-unavailable": exc.RemoteError(f"Service at {iq['from']} is unavailable.", module=sender),
|
|
332
|
+
"remote-server-not-found": exc.RemoteError(
|
|
333
|
+
f"Could not find remote server for {iq['from']}.", module=sender
|
|
334
|
+
),
|
|
335
|
+
}.get(condition, exc.RemoteError(f"Unexpected exception at {iq['from']}!", module=sender))
|
|
304
336
|
|
|
305
337
|
callback.set_exception(e)
|
|
306
338
|
|
|
@@ -503,10 +503,10 @@ class XmppComm(Comm):
|
|
|
503
503
|
# RPC layer's jabber_rpc_error event handling ever gets a chance to act on it,
|
|
504
504
|
# so the IQ-level "forbidden" condition (see Module ACLs) has to be read here.
|
|
505
505
|
if e.iq["error"]["condition"] == "forbidden":
|
|
506
|
-
raise exc.RemoteError(
|
|
507
|
-
raise exc.RemoteError(
|
|
506
|
+
raise exc.RemoteError(f"Forbidden to invoke {method} on {client}.", module=client)
|
|
507
|
+
raise exc.RemoteError(f"Could not call {method} on {client}.", module=client)
|
|
508
508
|
except slixmpp.exceptions.IqTimeout:
|
|
509
|
-
raise exc.RemoteTimeoutError(
|
|
509
|
+
raise exc.RemoteTimeoutError(f"Call to {method} on {client} timed out.", module=client)
|
|
510
510
|
|
|
511
511
|
async def _got_online(self, msg: Any) -> None:
|
|
512
512
|
"""If a new client connects, add it to list.
|
|
@@ -59,7 +59,10 @@ class IAcquisition(IRunning, IAbortable, metaclass=ABCMeta):
|
|
|
59
59
|
Result with time, ra, dec, alt, az, and an offset in whichever frame the mount supports.
|
|
60
60
|
|
|
61
61
|
Raises:
|
|
62
|
-
|
|
62
|
+
AbortedError: If the acquisition was aborted.
|
|
63
|
+
GeneralError: If a dependency (e.g. the camera) failed.
|
|
64
|
+
ImageError: If the calculated offset was too large or otherwise unusable.
|
|
65
|
+
AcquisitionError: If target could not be acquired within the given tolerance.
|
|
63
66
|
"""
|
|
64
67
|
...
|
|
65
68
|
|
|
@@ -54,7 +54,8 @@ class IAutoFocus(IRunning, IAbortable, metaclass=ABCMeta):
|
|
|
54
54
|
Result of autofocus.
|
|
55
55
|
|
|
56
56
|
Raises:
|
|
57
|
-
|
|
57
|
+
AbortedError: If the autofocus series was aborted.
|
|
58
|
+
FocusError: If focus could not be obtained.
|
|
58
59
|
"""
|
|
59
60
|
...
|
|
60
61
|
|
|
@@ -11,7 +11,11 @@ class ICalibrate(Interface, metaclass=ABCMeta):
|
|
|
11
11
|
|
|
12
12
|
@abstractmethod
|
|
13
13
|
async def calibrate(self, **kwargs: Any) -> None:
|
|
14
|
-
"""Calibrate the device.
|
|
14
|
+
"""Calibrate the device.
|
|
15
|
+
|
|
16
|
+
Raises:
|
|
17
|
+
GeneralError: If calibration failed.
|
|
18
|
+
"""
|
|
15
19
|
...
|
|
16
20
|
|
|
17
21
|
|
|
@@ -33,7 +33,7 @@ class IConfig(Interface, metaclass=ABCMeta):
|
|
|
33
33
|
Current value.
|
|
34
34
|
|
|
35
35
|
Raises:
|
|
36
|
-
|
|
36
|
+
InvalidArgumentError: If config item of given name does not exist.
|
|
37
37
|
"""
|
|
38
38
|
...
|
|
39
39
|
|
|
@@ -46,7 +46,8 @@ class IConfig(Interface, metaclass=ABCMeta):
|
|
|
46
46
|
value: New value.
|
|
47
47
|
|
|
48
48
|
Raises:
|
|
49
|
-
|
|
49
|
+
InvalidArgumentError: If config item of given name does not exist.
|
|
50
|
+
ValueError: If value is invalid.
|
|
50
51
|
"""
|
|
51
52
|
...
|
|
52
53
|
|
|
@@ -38,7 +38,8 @@ class IDataSequence(IAbortable, metaclass=ABCMeta):
|
|
|
38
38
|
during the wait.
|
|
39
39
|
|
|
40
40
|
Raises:
|
|
41
|
-
|
|
41
|
+
InvalidArgumentError: If count or delay is out of range.
|
|
42
|
+
DeviceBusyError: If the device is already busy (exposing or already running a
|
|
42
43
|
sequence).
|
|
43
44
|
"""
|
|
44
45
|
...
|
|
@@ -31,6 +31,8 @@ class IExposureTime(Interface, metaclass=ABCMeta):
|
|
|
31
31
|
|
|
32
32
|
Raises:
|
|
33
33
|
ValueError: If exposure time could not be set.
|
|
34
|
+
NotSupportedError: If this module doesn't support setting exposure time directly (e.g.
|
|
35
|
+
it's dictated by something else, like incoming science frames).
|
|
34
36
|
"""
|
|
35
37
|
...
|
|
36
38
|
|
|
@@ -35,7 +35,7 @@ class IFilters(IMotion, metaclass=ABCMeta):
|
|
|
35
35
|
filter_name: Name of filter to set.
|
|
36
36
|
|
|
37
37
|
Raises:
|
|
38
|
-
|
|
38
|
+
InvalidArgumentError: If an invalid filter was given.
|
|
39
39
|
MoveError: If filter wheel cannot be moved.
|
|
40
40
|
"""
|
|
41
41
|
...
|
|
@@ -21,7 +21,13 @@ class IFocusModel(Interface, metaclass=ABCMeta):
|
|
|
21
21
|
|
|
22
22
|
@abstractmethod
|
|
23
23
|
async def set_optimal_focus(self, **kwargs: Any) -> None:
|
|
24
|
-
"""Sets optimal focus.
|
|
24
|
+
"""Sets optimal focus.
|
|
25
|
+
|
|
26
|
+
Raises:
|
|
27
|
+
WeatherDataError: If the weather station returned an invalid temperature reading.
|
|
28
|
+
FocusTimeoutError: If a temperature module didn't respond in time.
|
|
29
|
+
MissingSensorError: If a configured sensor isn't in a module's temperature data.
|
|
30
|
+
"""
|
|
25
31
|
...
|
|
26
32
|
|
|
27
33
|
|
|
@@ -31,8 +31,9 @@ class IFocuser(IMotion, metaclass=ABCMeta):
|
|
|
31
31
|
focus: New focus value in mm.
|
|
32
32
|
|
|
33
33
|
Raises:
|
|
34
|
+
InvalidArgumentError: If given value is invalid.
|
|
35
|
+
AbortedError: If movement was aborted.
|
|
34
36
|
MoveError: If telescope cannot be moved.
|
|
35
|
-
InterruptedError: If movement was aborted.
|
|
36
37
|
"""
|
|
37
38
|
...
|
|
38
39
|
|
|
@@ -45,6 +46,7 @@ class IFocuser(IMotion, metaclass=ABCMeta):
|
|
|
45
46
|
|
|
46
47
|
Raises:
|
|
47
48
|
ValueError: If given value is invalid.
|
|
49
|
+
NotSupportedError: If this module doesn't support a separate focus offset.
|
|
48
50
|
MoveError: If telescope cannot be moved.
|
|
49
51
|
"""
|
|
50
52
|
...
|
|
@@ -36,7 +36,7 @@ class IMode(Interface, metaclass=ABCMeta):
|
|
|
36
36
|
group: Name of the group to set the mode for.
|
|
37
37
|
|
|
38
38
|
Raises:
|
|
39
|
-
|
|
39
|
+
InvalidArgumentError: If an invalid mode or group was given.
|
|
40
40
|
MoveError: If mode selector cannot be moved.
|
|
41
41
|
"""
|
|
42
42
|
...
|
|
@@ -34,6 +34,8 @@ class IPointingAltAz(Interface, metaclass=ABCMeta):
|
|
|
34
34
|
az: Az in deg to move to.
|
|
35
35
|
|
|
36
36
|
Raises:
|
|
37
|
+
NotSupportedError: If this device doesn't support Alt/Az pointing.
|
|
38
|
+
AltitudeLimitError: If the destination is below the configured altitude limit.
|
|
37
39
|
MoveError: If device could not be moved.
|
|
38
40
|
"""
|
|
39
41
|
...
|
|
@@ -20,8 +20,11 @@ class IPointingBody(Interface, metaclass=ABCMeta):
|
|
|
20
20
|
asteroid/comet designation known to JPL Horizons).
|
|
21
21
|
|
|
22
22
|
Raises:
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
NotSupportedError: If this device doesn't support body tracking.
|
|
24
|
+
BodyResolutionError: If body name is not resolvable.
|
|
25
|
+
MoveError: If telescope could not be moved. Also propagates whatever the underlying
|
|
26
|
+
RA/Dec move raises (e.g. MissingObserverError, AltitudeLimitError), since tracking
|
|
27
|
+
a body is implemented as resolving it and then moving there.
|
|
25
28
|
"""
|
|
26
29
|
...
|
|
27
30
|
|
{pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IPointingHeliocentricPolar.py
RENAMED
|
@@ -33,7 +33,9 @@ class IPointingHeliocentricPolar(Interface, metaclass=ABCMeta):
|
|
|
33
33
|
psi: Position angle around the solar disk, in degrees.
|
|
34
34
|
|
|
35
35
|
Raises:
|
|
36
|
-
MoveError: If device could not be moved.
|
|
36
|
+
MoveError: If device could not be moved. Also propagates whatever the underlying
|
|
37
|
+
RA/Dec move raises (e.g. MissingObserverError, AltitudeLimitError), since this is
|
|
38
|
+
typically implemented as converting to RA/Dec and then moving there.
|
|
37
39
|
"""
|
|
38
40
|
...
|
|
39
41
|
|
|
@@ -35,7 +35,9 @@ class IPointingHeliographicStonyhurst(Interface, metaclass=ABCMeta):
|
|
|
35
35
|
lat: Latitude in deg to track.
|
|
36
36
|
|
|
37
37
|
Raises:
|
|
38
|
-
MoveError: If device could not be moved.
|
|
38
|
+
MoveError: If device could not be moved. Also propagates whatever the underlying
|
|
39
|
+
RA/Dec move raises (e.g. MissingObserverError, AltitudeLimitError), since this is
|
|
40
|
+
typically implemented as converting to RA/Dec and then moving there.
|
|
39
41
|
"""
|
|
40
42
|
...
|
|
41
43
|
|
{pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IPointingHelioprojective.py
RENAMED
|
@@ -34,7 +34,9 @@ class IPointingHelioprojective(Interface, metaclass=ABCMeta):
|
|
|
34
34
|
theta_y: The theta_y coordinate.
|
|
35
35
|
|
|
36
36
|
Raises:
|
|
37
|
-
MoveError: If device could not be moved.
|
|
37
|
+
MoveError: If device could not be moved. Also propagates whatever the underlying
|
|
38
|
+
RA/Dec move raises (e.g. MissingObserverError, AltitudeLimitError), since this is
|
|
39
|
+
typically implemented as converting to RA/Dec and then moving there.
|
|
38
40
|
"""
|
|
39
41
|
...
|
|
40
42
|
|
{pyobs_core-2.0.0.dev26 → pyobs_core-2.0.0.dev28}/pyobs/interfaces/IPointingOrbitalElements.py
RENAMED
|
@@ -37,9 +37,12 @@ class IPointingOrbitalElements(Interface, metaclass=ABCMeta):
|
|
|
37
37
|
elements: Orbital elements of the body to track.
|
|
38
38
|
|
|
39
39
|
Raises:
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
nor perihelion_time given).
|
|
40
|
+
NotSupportedError: If this device doesn't support orbital-element tracking.
|
|
41
|
+
InvalidOrbitalElementsError: If elements are incomplete or inconsistent (neither
|
|
42
|
+
mean_anomaly nor perihelion_time given).
|
|
43
|
+
MoveError: If telescope could not be moved. Also propagates whatever the underlying
|
|
44
|
+
RA/Dec move raises (e.g. MissingObserverError, AltitudeLimitError), since tracking
|
|
45
|
+
orbital elements is implemented as propagating them and then moving there.
|
|
43
46
|
"""
|
|
44
47
|
...
|
|
45
48
|
|
|
@@ -34,6 +34,9 @@ class IPointingRaDec(Interface, metaclass=ABCMeta):
|
|
|
34
34
|
dec: Dec in deg to track.
|
|
35
35
|
|
|
36
36
|
Raises:
|
|
37
|
+
NotSupportedError: If this device doesn't support RA/Dec pointing.
|
|
38
|
+
MissingObserverError: If no observer is configured.
|
|
39
|
+
AltitudeLimitError: If the destination is below the configured altitude limit.
|
|
37
40
|
MoveError: If device could not be moved.
|
|
38
41
|
"""
|
|
39
42
|
...
|
|
@@ -12,7 +12,11 @@ class IPointingSeries(Interface, metaclass=ABCMeta):
|
|
|
12
12
|
|
|
13
13
|
@abstractmethod
|
|
14
14
|
async def add_pointing_measurement(self, **kwargs: Any) -> None:
|
|
15
|
-
"""Add a new measurement to the pointing series.
|
|
15
|
+
"""Add a new measurement to the pointing series.
|
|
16
|
+
|
|
17
|
+
Raises:
|
|
18
|
+
GeneralError: If the measurement could not be added.
|
|
19
|
+
"""
|
|
16
20
|
...
|
|
17
21
|
|
|
18
22
|
|
|
@@ -24,7 +24,11 @@ class IRotation(IMotion, metaclass=ABCMeta):
|
|
|
24
24
|
|
|
25
25
|
@abstractmethod
|
|
26
26
|
async def set_rotation(self, angle: Annotated[float, Unit.DEGREES], **kwargs: Any) -> None:
|
|
27
|
-
"""Sets the rotation angle to the given value in degrees.
|
|
27
|
+
"""Sets the rotation angle to the given value in degrees.
|
|
28
|
+
|
|
29
|
+
Raises:
|
|
30
|
+
MoveError: If the device could not be rotated.
|
|
31
|
+
"""
|
|
28
32
|
...
|
|
29
33
|
|
|
30
34
|
|
|
@@ -11,7 +11,13 @@ class IRunnable(IAbortable, metaclass=ABCMeta):
|
|
|
11
11
|
|
|
12
12
|
@abstractmethod
|
|
13
13
|
async def run(self, **kwargs: Any) -> None:
|
|
14
|
-
"""Perform module task
|
|
14
|
+
"""Perform module task
|
|
15
|
+
|
|
16
|
+
Raises:
|
|
17
|
+
DeviceBusyError: If this task is already running.
|
|
18
|
+
ScriptError: ScriptRunner-based implementations wrap whatever the underlying script
|
|
19
|
+
raises that isn't already a domain exception.
|
|
20
|
+
"""
|
|
15
21
|
...
|
|
16
22
|
|
|
17
23
|
|
|
@@ -12,7 +12,11 @@ class ISyncTarget(Interface, metaclass=ABCMeta):
|
|
|
12
12
|
|
|
13
13
|
@abstractmethod
|
|
14
14
|
async def sync_target(self, **kwargs: Any) -> None:
|
|
15
|
-
"""Synchronize device on current target.
|
|
15
|
+
"""Synchronize device on current target.
|
|
16
|
+
|
|
17
|
+
Raises:
|
|
18
|
+
GeneralError: If synchronization failed.
|
|
19
|
+
"""
|
|
16
20
|
...
|
|
17
21
|
|
|
18
22
|
|
|
@@ -42,6 +42,10 @@ class IWeather(IStartStop, metaclass=ABCMeta):
|
|
|
42
42
|
|
|
43
43
|
Returns:
|
|
44
44
|
Current reading for the given sensor.
|
|
45
|
+
|
|
46
|
+
Raises:
|
|
47
|
+
InvalidArgumentError: If station or sensor is unknown.
|
|
48
|
+
WeatherResponseError: If the underlying weather station's response is malformed.
|
|
45
49
|
"""
|
|
46
50
|
...
|
|
47
51
|
|
|
@@ -30,10 +30,6 @@ from pyobs.utils.enums import ExposureStatus, ImageType
|
|
|
30
30
|
log = logging.getLogger(__name__)
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
class CameraException(Exception):
|
|
34
|
-
pass
|
|
35
|
-
|
|
36
|
-
|
|
37
33
|
class ExposureInfo(NamedTuple):
|
|
38
34
|
"""Info about a running exposure."""
|
|
39
35
|
|
|
@@ -113,7 +109,7 @@ class BaseCamera(
|
|
|
113
109
|
self._sequence_delay_abort = asyncio.Event()
|
|
114
110
|
|
|
115
111
|
# register exception
|
|
116
|
-
|
|
112
|
+
self._register_exception(exc.GrabImageError, 3, timespan=600, callback=self._default_remote_error_callback)
|
|
117
113
|
|
|
118
114
|
async def open(self) -> None:
|
|
119
115
|
"""Open module."""
|
|
@@ -226,6 +222,7 @@ class BaseCamera(
|
|
|
226
222
|
The actual image.
|
|
227
223
|
|
|
228
224
|
Raises:
|
|
225
|
+
AbortedError: If the exposure was cancelled via abort_event.
|
|
229
226
|
GrabImageError: If exposure was not successful.
|
|
230
227
|
"""
|
|
231
228
|
...
|
|
@@ -268,7 +265,7 @@ class BaseCamera(
|
|
|
268
265
|
if image is None or image.safe_data is None:
|
|
269
266
|
raise exc.GrabImageError("Could not take image.")
|
|
270
267
|
|
|
271
|
-
except exc.
|
|
268
|
+
except exc.PyobsError:
|
|
272
269
|
# exposure was not successful (aborted?), so reset everything and re-raise
|
|
273
270
|
self._exposure = None
|
|
274
271
|
raise
|
|
@@ -349,12 +346,13 @@ class BaseCamera(
|
|
|
349
346
|
Name of image that was taken.
|
|
350
347
|
|
|
351
348
|
Raises:
|
|
349
|
+
DeviceBusyError: If the camera is already busy (exposing or running a sequence).
|
|
352
350
|
GrabImageError: If there was a problem grabbing the image.
|
|
353
351
|
"""
|
|
354
352
|
|
|
355
353
|
# are we exposing?
|
|
356
354
|
if self._camera_status != ExposureStatus.IDLE:
|
|
357
|
-
raise
|
|
355
|
+
raise exc.DeviceBusyError("Cannot start new exposure because camera is not idle.")
|
|
358
356
|
await self._change_exposure_status(ExposureStatus.EXPOSING)
|
|
359
357
|
|
|
360
358
|
# expose
|
|
@@ -384,16 +382,17 @@ class BaseCamera(
|
|
|
384
382
|
Does not apply after the last image.
|
|
385
383
|
|
|
386
384
|
Raises:
|
|
387
|
-
|
|
385
|
+
InvalidArgumentError: If count or delay is out of range.
|
|
386
|
+
DeviceBusyError: If camera is already busy (exposing or already running a sequence).
|
|
388
387
|
"""
|
|
389
388
|
if count < 1:
|
|
390
|
-
raise
|
|
389
|
+
raise exc.InvalidArgumentError("count must be >= 1.")
|
|
391
390
|
if delay < 0:
|
|
392
|
-
raise
|
|
391
|
+
raise exc.InvalidArgumentError("delay must be >= 0.")
|
|
393
392
|
|
|
394
393
|
# already running a sequence, or mid-exposure outside of one?
|
|
395
394
|
if self._sequence_count_left > 0 or self._camera_status != ExposureStatus.IDLE:
|
|
396
|
-
raise
|
|
395
|
+
raise exc.DeviceBusyError("Cannot start new sequence because camera is not idle.")
|
|
397
396
|
|
|
398
397
|
log.info("Starting sequence of %d images...", count)
|
|
399
398
|
self._sequence_count_left = count
|
|
@@ -406,7 +405,7 @@ class BaseCamera(
|
|
|
406
405
|
while self._sequence_count_left > 0:
|
|
407
406
|
try:
|
|
408
407
|
await self.grab_data(broadcast=broadcast)
|
|
409
|
-
except exc.
|
|
408
|
+
except exc.PyobsError:
|
|
410
409
|
log.exception("Grab failed during sequence, aborting sequence.")
|
|
411
410
|
break
|
|
412
411
|
self._sequence_count_left -= 1
|
|
@@ -546,4 +545,4 @@ class BaseCamera(
|
|
|
546
545
|
image.data = image.data[::-1, ::-1]
|
|
547
546
|
|
|
548
547
|
|
|
549
|
-
__all__ = ["BaseCamera"
|
|
548
|
+
__all__ = ["BaseCamera"]
|
|
@@ -12,6 +12,7 @@ from pyobs.events import ExposureStatusChangedEvent, NewSpectrumEvent
|
|
|
12
12
|
from pyobs.interfaces import ExposureState, IExposure, ISpectrograph
|
|
13
13
|
from pyobs.mixins.fitsheader import SpectrumFitsHeaderMixin
|
|
14
14
|
from pyobs.modules import Module, timeout
|
|
15
|
+
from pyobs.utils import exceptions as exc
|
|
15
16
|
from pyobs.utils.enums import ExposureStatus
|
|
16
17
|
|
|
17
18
|
log = logging.getLogger(__name__)
|
|
@@ -80,6 +81,7 @@ class BaseSpectrograph(Module, SpectrumFitsHeaderMixin, ISpectrograph, IExposure
|
|
|
80
81
|
The actual image and, if present, a filename.
|
|
81
82
|
|
|
82
83
|
Raises:
|
|
84
|
+
AbortedError: If the exposure was cancelled via abort_event.
|
|
83
85
|
ValueError: If exposure was not successful.
|
|
84
86
|
"""
|
|
85
87
|
...
|
|
@@ -169,17 +171,21 @@ class BaseSpectrograph(Module, SpectrumFitsHeaderMixin, ISpectrograph, IExposure
|
|
|
169
171
|
|
|
170
172
|
Returns:
|
|
171
173
|
Name of image that was taken.
|
|
174
|
+
|
|
175
|
+
Raises:
|
|
176
|
+
DeviceBusyError: If the spectrograph is already busy (exposing).
|
|
177
|
+
GrabImageError: If there was a problem grabbing the spectrum.
|
|
172
178
|
"""
|
|
173
179
|
|
|
174
180
|
# are we exposing?
|
|
175
181
|
if self._spectrograph_status != ExposureStatus.IDLE:
|
|
176
|
-
raise
|
|
182
|
+
raise exc.DeviceBusyError("Cannot start new exposure because spectrograph is not idle.")
|
|
177
183
|
await self._change_exposure_status(ExposureStatus.EXPOSING)
|
|
178
184
|
|
|
179
185
|
# expose
|
|
180
186
|
hdu, filename = await self.__expose(broadcast)
|
|
181
187
|
if hdu is None:
|
|
182
|
-
raise
|
|
188
|
+
raise exc.GrabImageError("Could not take spectrum.")
|
|
183
189
|
else:
|
|
184
190
|
if filename is None:
|
|
185
191
|
raise ValueError("Spectrum has not been saved, so cannot be retrieved by filename.")
|