pyobs-core 2.0.0.dev94__tar.gz → 2.0.0.dev97__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.dev94 → pyobs_core-2.0.0.dev97}/PKG-INFO +1 -1
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/robotic/scheduler.py +1 -1
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/calibration/darkbias.py +8 -4
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/calibration/pointing.py +4 -2
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/calibration/skyflats.py +27 -11
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/control/cases.py +6 -2
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/control/conditional.py +7 -3
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/control/parallel.py +7 -2
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/control/selector.py +4 -2
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/control/sequential.py +6 -2
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/imaging/autofocus.py +11 -5
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/imaging/imaging.py +56 -21
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/script.py +3 -1
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/utils/callmodule.py +6 -4
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/utils/debugtrigger.py +3 -1
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/utils/log.py +3 -1
- pyobs_core-2.0.0.dev97/pyobs/robotic/storage/portal/__init__.py +4 -0
- {pyobs_core-2.0.0.dev94/pyobs/robotic/storage/backend → pyobs_core-2.0.0.dev97/pyobs/robotic/storage/portal}/observationarchive.py +13 -13
- {pyobs_core-2.0.0.dev94/pyobs/robotic/storage/backend → pyobs_core-2.0.0.dev97/pyobs/robotic/storage/portal}/taskarchive.py +16 -16
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/task.py +3 -3
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/utils/skyflats/priorities/archive.py +6 -5
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/utils/skyflats/priorities/const.py +5 -1
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyproject.toml +1 -1
- pyobs_core-2.0.0.dev94/pyobs/robotic/storage/backend/__init__.py +0 -4
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/.gitignore +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/LICENSE +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/application.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/background_task.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/cli/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/cli/_cli.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/cli/pyobs.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/cli/pyobsd.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/cli/pyobsw.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/comm/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/comm/comm.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/comm/commlogging.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/comm/dummy/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/comm/dummy/dummycomm.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/comm/local/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/comm/local/localcomm.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/comm/local/localnetwork.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/comm/proxy.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/comm/xmpp/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/comm/xmpp/rpc.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/comm/xmpp/serializer.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/comm/xmpp/xep_0009/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/comm/xmpp/xep_0009/binding.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/comm/xmpp/xep_0009/rpc.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/comm/xmpp/xep_0009_timeout/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/comm/xmpp/xep_0009_timeout/rpc.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/comm/xmpp/xep_0009_timeout/stanza/RPC.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/comm/xmpp/xep_0009_timeout/stanza/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/comm/xmpp/xmppclient.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/comm/xmpp/xmppcomm.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/events/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/events/badweather.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/events/event.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/events/exposurestatuschanged.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/events/filterchanged.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/events/focusfound.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/events/goodweather.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/events/log.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/events/modechanged.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/events/moduleclosed.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/events/moduleopened.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/events/motionstatuschanged.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/events/move.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/events/newimage.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/events/newspectrum.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/events/offsets.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/events/roofclosing.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/events/roofopened.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/events/taskfailed.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/events/taskfinished.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/events/taskstarted.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/events/testevent.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/image.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/meta/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/meta/altazoffsets.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/meta/exptime.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/meta/genericoffset.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/meta/onskydistance.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/meta/pixeloffsets.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/meta/radecoffsets.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/meta/skyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processor.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/_daobackgroundremover.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/annotation/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/annotation/_pillow.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/annotation/circle.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/annotation/crosshair.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/annotation/text.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/astrometry/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/astrometry/_dotnet_request.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/astrometry/_dotnet_request_builder.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/astrometry/_dotnet_request_logger.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/astrometry/_dotnet_response_saver.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/astrometry/astrometry.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/astrometry/dotnet.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/calibration/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/calibration/_calibration_cache.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/calibration/_ccddata_calibrator.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/calibration/calibration.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/detection/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/detection/_pysep_stats_calculator.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/detection/_source_catalog.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/detection/daophot.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/detection/pysep.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/detection/simpledisk.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/detection/sourcedetection.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/exptime/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/exptime/exptime.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/exptime/star.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/image/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/image/addfitsheaders.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/image/download.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/image/flip.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/image/grayscale.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/image/httpserver.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/image/normalize.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/image/save.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/image/saveimage.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/image/smooth.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/image/softbin.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/misc/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/misc/addmask.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/misc/catalogcircularmask.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/misc/circularmask.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/misc/createfilename.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/misc/imagesourcefilter.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/misc/removebackground.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/modules/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/modules/getfitsheaders.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/offsets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/offsets/astrometry.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/offsets/brighteststar.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/offsets/brighteststar_guiding.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/offsets/dummyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/offsets/dummyskyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/offsets/fitsheader.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/offsets/offsets.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/offsets/pixeloffsets.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/offsets/projected.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/offsets/spilled_light.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/photometry/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/photometry/_photometry_calculator.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/photometry/_photutil_aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/photometry/_sep_aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/photometry/aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/photometry/photometry.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/photometry/photutil.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/photometry/pysep.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/wcs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/images/processors/wcs/solarhelioprojective.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IAbortable.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IAcquisition.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IAutoFocus.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IAutoGuiding.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IAutonomous.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IBinning.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/ICalibrate.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/ICamera.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IConfig.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/ICooling.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IData.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IDataSequence.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IDome.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IExposure.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IExposureTime.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IFilters.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IFitsHeaderAfter.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IFitsHeaderBefore.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IFlatField.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IFocusModel.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IFocuser.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IGain.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IImageFormat.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IImageType.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IMode.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IModule.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IMotion.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IMultiFiber.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IOffsetsAltAz.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IOffsetsRaDec.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IPointingAltAz.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IPointingBody.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IPointingHeliocentricPolar.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IPointingHeliographicStonyhurst.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IPointingHelioprojective.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IPointingOrbitalElements.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IPointingRaDec.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IPointingSeries.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IReady.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IRoof.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IRotation.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IRunnable.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IRunning.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IScriptRunner.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/ISpectrograph.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IStartStop.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IStructuredConfig.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/ISyncTarget.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/ITelescope.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/ITemperatures.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/ITrackingMode.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/ITrackingRate.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IVideo.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IWeather.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/IWindow.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/interfaces/interface.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/mixins/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/mixins/camerasettings.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/mixins/fitsheader.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/mixins/fitsnamespace.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/mixins/follow.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/mixins/motionstatus.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/mixins/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/mixins/waitformotion.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/mixins/weatheraware.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/camera/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/camera/adaptive.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/camera/basecamera.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/camera/basespectrograph.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/camera/basevideo.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/camera/dummycamera.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/camera/dummyspectrograph.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/camera/dummyvideo.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/camera/pipelinecamera.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/flatfield/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/flatfield/flatfield.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/flatfield/pointing.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/flatfield/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/focus/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/focus/dummyautofocus.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/focus/focusmodel.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/focus/focusseries.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/image/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/image/imagewatcher.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/image/imagewriter.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/image/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/image/seeing.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/module.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/pointing/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/pointing/_base.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/pointing/_baseguiding.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/pointing/acquisition.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/pointing/autoguiding.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/pointing/dummyacquisition.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/pointing/dummyguiding.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/pointing/guidingstatistics/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/pointing/guidingstatistics/guidingstatistics.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/pointing/guidingstatistics/pixeloffset.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/pointing/guidingstatistics/skyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/pointing/guidingstatistics/uptime.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/pointing/scienceframeguiding.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/robotic/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/robotic/mastermind.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/robotic/pointing.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/robotic/scriptrunner.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/roof/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/roof/basedome.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/roof/baseroof.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/roof/dummyroof.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/telescope/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/telescope/_dummytelescopebase.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/telescope/basetelescope.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/telescope/dummyaltaztelescope.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/telescope/dummyradectelescope.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/telescope/dummysolartelescope.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/test/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/test/standalone.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/utils/dummymode.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/utils/fluentlogger.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/utils/httpfilecache.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/utils/kiosk.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/utils/matrix.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/utils/stellarium.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/utils/telegram.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/utils/trigger.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/weather/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/weather/mockweather.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/weather/weather.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/weather/weather_api.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/modules/weather/weather_state.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/object.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/py.typed +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/observation.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/_executor.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/astroplanscheduler.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/constraints/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/constraints/airmassconstraint.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/constraints/constraint.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/constraints/moonilluminationconstraint.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/constraints/moonseparationconstraint.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/constraints/solarelevationconstraint.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/constraints/timeconstraint.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/dataprovider.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/merits/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/merits/aftertime.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/merits/beforetime.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/merits/constant.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/merits/follow.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/merits/interval.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/merits/merit.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/merits/pernight.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/merits/random.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/merits/timewindow.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/merits/transit.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/observationarchiveevolution.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/ondemandscheduler.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/targets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/targets/dynamictarget.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/targets/heliocentricpolartarget.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/targets/helioprojectivetarget.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/targets/picker/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/targets/picker/csvpicker.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/targets/picker/picker.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/targets/siderealtarget.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/targets/target.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scheduler/taskscheduler.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/calibration/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/control/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/exceptions.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/imaging/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/imaging/transitimaging.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/filesystem/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/filesystem/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/filesystem/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/lco/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/lco/_portal.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/lco/_schedulereader.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/lco/_schedulewriter.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/lco/configdb.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/lco/mockobservationarchive.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/lco/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/lco/scripts/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/lco/scripts/autofocus.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/lco/scripts/default.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/lco/scripts/script.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/lco/task.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/lco/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/lco/taskrunner.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/memory/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/memory/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/memory/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/storage/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/taskrunner.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/utils/archive/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/utils/archive/archive.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/utils/archive/local_archive.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/utils/archive/pyobs_archive.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/utils/exptime/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/utils/exptime/exptime.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/utils/exptime/stellarexptime.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/utils/skyflats/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/utils/skyflats/exptimeeval.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/utils/skyflats/flatfielder.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/utils/skyflats/pointing/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/utils/skyflats/pointing/base.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/utils/skyflats/pointing/static.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/utils/skyflats/priorities/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/utils/skyflats/priorities/base.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/utils/skyflats/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/average.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/cache.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/config.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/config_schema.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/coordinates.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/curvefit.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/enums.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/exceptions.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/fits.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/focusseries/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/focusseries/base.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/focusseries/photometry.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/focusseries/projection.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/grids/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/grids/filters.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/grids/grid.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/grids/gridnode.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/grids/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/gui/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/gui/camera/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/gui/camera/binningwidget.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/gui/camera/datadisplaywidget.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/gui/camera/exposewidget.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/gui/camera/exposuretimewidget.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/gui/camera/imageformatwidget.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/gui/camera/listpickerdialog.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/gui/camera/windowingwidget.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/http.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/influxdb.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/logger.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/logging/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/logging/context.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/logging/resolvableerror.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/modulegui.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/offsets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/offsets/applyaltazoffsets.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/offsets/applyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/offsets/applyradecoffsets.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/parallel.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/pipeline/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/pipeline/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/pipeline/progress.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/pipeline/reduction.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/pipeline/reduction_base.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/publisher/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/publisher/csv.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/publisher/http.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/publisher/log.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/publisher/multi.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/publisher/publisher.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/serialization.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/shellcommand.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/threads/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/threads/lockwithabort.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/time.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/units.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/utils/versions.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/version.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/vfs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/vfs/archivefile.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/vfs/bufferedfile.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/vfs/file.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/vfs/filelists/__init__.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/vfs/filelists/filelist.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/vfs/filelists/testing.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/vfs/httpfile.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/vfs/localfile.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/vfs/memfile.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/vfs/sftpfile.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/vfs/smbfile.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/vfs/sshfile.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/vfs/tempfile.py +0 -0
- {pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/vfs/vfs.py +0 -0
|
@@ -102,7 +102,7 @@ class Scheduler(Module, IStartStop, IRunnable):
|
|
|
102
102
|
|
|
103
103
|
# get scheduler
|
|
104
104
|
self._task_archive = self.add_child_object(tasks, TaskArchive, on_tasks_changed=self._update_schedule)
|
|
105
|
-
#
|
|
105
|
+
# PortalObservationArchive declares auto_update and gates its own polling loop on it --
|
|
106
106
|
# since we already drive updates via on_tasks_changed above, that poller must stay off.
|
|
107
107
|
# Other ObservationArchive implementations (e.g. LcoObservationArchive) don't declare it at
|
|
108
108
|
# all, so it must not be injected unconditionally.
|
{pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/calibration/darkbias.py
RENAMED
|
@@ -3,6 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
from typing import TYPE_CHECKING, Annotated
|
|
5
5
|
|
|
6
|
+
from pydantic import Field
|
|
7
|
+
|
|
6
8
|
from pyobs.interfaces import (
|
|
7
9
|
IBinning,
|
|
8
10
|
IData,
|
|
@@ -23,10 +25,12 @@ log = logging.getLogger(__name__)
|
|
|
23
25
|
class DarkBiasScript(Script):
|
|
24
26
|
"""Script for running darks or biases."""
|
|
25
27
|
|
|
26
|
-
camera: Annotated[str, IData, IBinning, IWindow, IExposureTime, IImageType]
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
camera: Annotated[str, IData, IBinning, IWindow, IExposureTime, IImageType] = Field(
|
|
29
|
+
description="Name of the camera module to expose with."
|
|
30
|
+
)
|
|
31
|
+
count: int = Field(default=20, description="Number of exposures to take.")
|
|
32
|
+
exptime: float = Field(default=0, description="Exposure time in seconds. 0 takes a bias, anything else a dark.")
|
|
33
|
+
binning: tuple[int, int] = Field(default=(1, 1), description="Detector binning as (x, y).")
|
|
30
34
|
|
|
31
35
|
async def can_run(self, data: TaskData | None) -> bool:
|
|
32
36
|
"""Whether this config can currently run.
|
{pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/calibration/pointing.py
RENAMED
|
@@ -3,6 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
from typing import TYPE_CHECKING, Annotated
|
|
5
5
|
|
|
6
|
+
from pydantic import Field
|
|
7
|
+
|
|
6
8
|
from pyobs.interfaces import IPointingAltAz, IReady
|
|
7
9
|
from pyobs.robotic.scripts import Script
|
|
8
10
|
from pyobs.robotic.utils.skyflats.pointing import SkyFlatsBasePointing
|
|
@@ -17,8 +19,8 @@ log = logging.getLogger(__name__)
|
|
|
17
19
|
class PointingScript(Script):
|
|
18
20
|
"""Script for pointing the telescope for flats."""
|
|
19
21
|
|
|
20
|
-
telescope: Annotated[str, IPointingAltAz, IReady]
|
|
21
|
-
pointing: SkyFlatsBasePointing
|
|
22
|
+
telescope: Annotated[str, IPointingAltAz, IReady] = Field(description="Name of the telescope module to point.")
|
|
23
|
+
pointing: SkyFlatsBasePointing = Field(description="Strategy used to compute the flat-field pointing.")
|
|
22
24
|
|
|
23
25
|
async def can_run(self, data: TaskData | None) -> bool:
|
|
24
26
|
"""Whether this config can currently run.
|
{pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/calibration/skyflats.py
RENAMED
|
@@ -3,6 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
from typing import TYPE_CHECKING, Annotated
|
|
5
5
|
|
|
6
|
+
from pydantic import Field
|
|
7
|
+
|
|
6
8
|
from pyobs.interfaces import IBinning, IFilters, IFlatField, IReady, IRoof, ITelescope
|
|
7
9
|
from pyobs.robotic.scripts import Script
|
|
8
10
|
from pyobs.robotic.utils.skyflats.priorities.base import SkyflatPriorities
|
|
@@ -21,17 +23,31 @@ FlatFunctions = str | dict[str, str | dict[str, str]]
|
|
|
21
23
|
class SkyFlatsScript(Script):
|
|
22
24
|
"""Script for scheduling and running skyflats using an IFlatField module."""
|
|
23
25
|
|
|
24
|
-
roof: Annotated[str, IRoof]
|
|
25
|
-
telescope: Annotated[str, ITelescope]
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
roof: Annotated[str, IRoof] = Field(description="Name of the roof module, checked to be open before starting.")
|
|
27
|
+
telescope: Annotated[str, ITelescope] = Field(
|
|
28
|
+
description="Name of the telescope module, checked to be ready before starting."
|
|
29
|
+
)
|
|
30
|
+
flatfield: Annotated[str, IBinning, IFilters, IFlatField] = Field(
|
|
31
|
+
description="Name of the module that takes the flat-field exposures."
|
|
32
|
+
)
|
|
33
|
+
functions: FlatFunctions = Field(
|
|
34
|
+
default={},
|
|
35
|
+
description=(
|
|
36
|
+
"Exposure-time function(s) of solar altitude `h` in degrees, e.g. 'exp(-0.9*(h+3.9))'. "
|
|
37
|
+
"Either a single expression for all filters/binnings, a dict keyed by binning ('1x1') or "
|
|
38
|
+
"filter, or a nested dict of binning -> filter -> expression."
|
|
39
|
+
),
|
|
40
|
+
)
|
|
41
|
+
priorities: SkyflatPriorities = Field(description="Strategy for prioritizing filter/binning combinations.")
|
|
42
|
+
min_exptime: float = Field(default=0.5, description="Minimum acceptable exposure time in seconds.")
|
|
43
|
+
max_exptime: float = Field(default=5, description="Maximum acceptable exposure time in seconds.")
|
|
44
|
+
timespan: float = Field(default=7200, description="Time span in seconds to schedule flats over.")
|
|
45
|
+
filter_change: float = Field(default=30, description="Estimated time in seconds to change a filter.")
|
|
46
|
+
count: int = Field(default=20, description="Number of exposures to take per filter/binning combination.")
|
|
47
|
+
readout: dict[str, float] | None = Field(
|
|
48
|
+
default=None,
|
|
49
|
+
description='Readout time in seconds per binning, keyed as "BxB" (e.g. "2x2"). Assumes 0s if unset.',
|
|
50
|
+
)
|
|
35
51
|
|
|
36
52
|
async def can_run(self, data: TaskData | None) -> bool:
|
|
37
53
|
"""Whether this config can currently run.
|
|
@@ -4,6 +4,8 @@ import logging
|
|
|
4
4
|
from datetime import UTC, datetime
|
|
5
5
|
from typing import TYPE_CHECKING
|
|
6
6
|
|
|
7
|
+
from pydantic import Field
|
|
8
|
+
|
|
7
9
|
if TYPE_CHECKING:
|
|
8
10
|
from pyobs.robotic.task import TaskData
|
|
9
11
|
from pyobs.utils.time import Time
|
|
@@ -16,8 +18,10 @@ log = logging.getLogger(__name__)
|
|
|
16
18
|
class CasesRunner(Script):
|
|
17
19
|
"""Script for distinguishing cases."""
|
|
18
20
|
|
|
19
|
-
expression: str
|
|
20
|
-
cases: dict[str | int | float, Script]
|
|
21
|
+
expression: str = Field(description="Python expression to evaluate; its value selects which script to run.")
|
|
22
|
+
cases: dict[str | int | float, Script] = Field(
|
|
23
|
+
description='Scripts to run, keyed by the value of `expression`. Use key "else" for a fallback.'
|
|
24
|
+
)
|
|
21
25
|
|
|
22
26
|
def __get_script(self) -> Script:
|
|
23
27
|
# evaluate condition
|
{pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/control/conditional.py
RENAMED
|
@@ -4,6 +4,8 @@ import logging
|
|
|
4
4
|
from datetime import UTC, datetime
|
|
5
5
|
from typing import TYPE_CHECKING
|
|
6
6
|
|
|
7
|
+
from pydantic import Field
|
|
8
|
+
|
|
7
9
|
if TYPE_CHECKING:
|
|
8
10
|
from pyobs.robotic.task import TaskData
|
|
9
11
|
from pyobs.utils.time import Time
|
|
@@ -16,9 +18,11 @@ log = logging.getLogger(__name__)
|
|
|
16
18
|
class ConditionalRunner(Script):
|
|
17
19
|
"""Script for running an if condition."""
|
|
18
20
|
|
|
19
|
-
condition: str
|
|
20
|
-
true: Script
|
|
21
|
-
false: Script | None =
|
|
21
|
+
condition: str = Field(description="Python expression to evaluate; run `true` if truthy, `false` otherwise.")
|
|
22
|
+
true: Script = Field(description="Script to run if `condition` is truthy.")
|
|
23
|
+
false: Script | None = Field(
|
|
24
|
+
default=None, description="Script to run if `condition` is falsy. Does nothing if unset."
|
|
25
|
+
)
|
|
22
26
|
|
|
23
27
|
def __get_script(self) -> Script | None:
|
|
24
28
|
# evaluate condition
|
|
@@ -4,6 +4,8 @@ import asyncio
|
|
|
4
4
|
import logging
|
|
5
5
|
from typing import TYPE_CHECKING
|
|
6
6
|
|
|
7
|
+
from pydantic import Field
|
|
8
|
+
|
|
7
9
|
if TYPE_CHECKING:
|
|
8
10
|
from pyobs.robotic.task import TaskData
|
|
9
11
|
from pyobs.utils.time import Time
|
|
@@ -22,8 +24,11 @@ async def _run_script(script: Script, data: TaskData | None) -> None:
|
|
|
22
24
|
class ParallelRunner(Script):
|
|
23
25
|
"""Script for running other scripts in parallel."""
|
|
24
26
|
|
|
25
|
-
scripts: list[Script]
|
|
26
|
-
check_all_can_run: bool =
|
|
27
|
+
scripts: list[Script] = Field(description="Scripts to run concurrently.")
|
|
28
|
+
check_all_can_run: bool = Field(
|
|
29
|
+
default=True,
|
|
30
|
+
description="If set, all scripts must be able to run for this script to run; otherwise, any one suffices.",
|
|
31
|
+
)
|
|
27
32
|
|
|
28
33
|
async def can_run(self, data: TaskData | None) -> bool:
|
|
29
34
|
results = [await s.can_run(data) for s in self.scripts]
|
|
@@ -3,6 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
from typing import TYPE_CHECKING, Annotated
|
|
5
5
|
|
|
6
|
+
from pydantic import Field
|
|
7
|
+
|
|
6
8
|
from pyobs.interfaces import IMotion
|
|
7
9
|
from pyobs.interfaces.IMode import IMode
|
|
8
10
|
from pyobs.robotic.scripts import Script
|
|
@@ -18,8 +20,8 @@ log = logging.getLogger(__name__)
|
|
|
18
20
|
class SelectorScript(Script):
|
|
19
21
|
"""Script for running Mode Selection."""
|
|
20
22
|
|
|
21
|
-
mode: str
|
|
22
|
-
selector: Annotated[str, IMode, IMotion]
|
|
23
|
+
mode: str = Field(description="Name of the mode to select.")
|
|
24
|
+
selector: Annotated[str, IMode, IMotion] = Field(description="Name of the mode-selection module.")
|
|
23
25
|
|
|
24
26
|
async def can_run(self, data: TaskData | None) -> bool:
|
|
25
27
|
"""Whether this config can currently run.
|
{pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/control/sequential.py
RENAMED
|
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING
|
|
|
5
5
|
|
|
6
6
|
import astropy.units as u
|
|
7
7
|
from astropy.time import TimeDelta
|
|
8
|
+
from pydantic import Field
|
|
8
9
|
|
|
9
10
|
if TYPE_CHECKING:
|
|
10
11
|
from pyobs.robotic.task import TaskData
|
|
@@ -17,8 +18,11 @@ log = logging.getLogger(__name__)
|
|
|
17
18
|
class SequentialRunner(Script):
|
|
18
19
|
"""Script for running a sequence of other scripts."""
|
|
19
20
|
|
|
20
|
-
scripts: list[Script]
|
|
21
|
-
check_all_can_run: bool =
|
|
21
|
+
scripts: list[Script] = Field(description="Scripts to run in sequence, each only if it can run.")
|
|
22
|
+
check_all_can_run: bool = Field(
|
|
23
|
+
default=True,
|
|
24
|
+
description="If set, all scripts must be able to run for this script to run; otherwise, only the first must.",
|
|
25
|
+
)
|
|
22
26
|
|
|
23
27
|
async def can_run(self, data: TaskData | None) -> bool:
|
|
24
28
|
if self.check_all_can_run:
|
{pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/imaging/autofocus.py
RENAMED
|
@@ -3,6 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
from typing import TYPE_CHECKING, Annotated
|
|
5
5
|
|
|
6
|
+
from pydantic import Field
|
|
7
|
+
|
|
6
8
|
from pyobs.interfaces import IAutoFocus, IMotion, IPointingRaDec, IReady, ITelescope
|
|
7
9
|
from pyobs.robotic.scripts import Script
|
|
8
10
|
from pyobs.utils.time import Time
|
|
@@ -16,11 +18,15 @@ log = logging.getLogger(__name__)
|
|
|
16
18
|
class AutoFocusScript(Script):
|
|
17
19
|
"""Script for running autofocus series."""
|
|
18
20
|
|
|
19
|
-
autofocus: Annotated[str, IAutoFocus] =
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
autofocus: Annotated[str, IAutoFocus] = Field(
|
|
22
|
+
default="autofocus", description="Name of the auto-focus module to run the series with."
|
|
23
|
+
)
|
|
24
|
+
telescope: Annotated[str, ITelescope, IPointingRaDec] = Field(
|
|
25
|
+
default="telescope", description="Name of the telescope module, moved to the target and stopped afterwards."
|
|
26
|
+
)
|
|
27
|
+
count: int = Field(default=5, description="Number of focus steps to take in the series.")
|
|
28
|
+
step: float = Field(default=0.1, description="Focus step size.")
|
|
29
|
+
exposure_time: float = Field(default=2.0, description="Exposure time in seconds for each focus step.")
|
|
24
30
|
|
|
25
31
|
async def can_run(self, data: TaskData | None) -> bool:
|
|
26
32
|
"""Whether this config can currently run.
|
|
@@ -38,26 +38,42 @@ log = logging.getLogger(__name__)
|
|
|
38
38
|
class AcquisitionConfig(BaseModel):
|
|
39
39
|
model_config = ConfigDict(extra="forbid")
|
|
40
40
|
|
|
41
|
-
enabled: bool =
|
|
42
|
-
|
|
41
|
+
enabled: bool = Field(
|
|
42
|
+
default=True, description="Whether to perform acquisition before starting this configuration."
|
|
43
|
+
)
|
|
44
|
+
optional: bool = Field(
|
|
45
|
+
default=False, description="If acquisition fails, continue without it instead of aborting the script."
|
|
46
|
+
)
|
|
43
47
|
|
|
44
48
|
|
|
45
49
|
class GuidingConfig(BaseModel):
|
|
46
50
|
model_config = ConfigDict(extra="forbid")
|
|
47
51
|
|
|
48
|
-
enabled: bool = True
|
|
49
|
-
optional: bool =
|
|
52
|
+
enabled: bool = Field(default=True, description="Whether to start auto-guiding before starting this configuration.")
|
|
53
|
+
optional: bool = Field(
|
|
54
|
+
default=False, description="If starting auto-guiding fails, continue without it instead of aborting the script."
|
|
55
|
+
)
|
|
50
56
|
|
|
51
57
|
|
|
52
58
|
class InstrumentConfig(BaseModel):
|
|
53
59
|
model_config = ConfigDict(extra="forbid")
|
|
54
60
|
|
|
55
|
-
exposure_time: float | ExposureTimeProvider =
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
exposure_time: float | ExposureTimeProvider = Field(
|
|
62
|
+
default=0.0, description="Exposure time in seconds, or a provider that computes it dynamically."
|
|
63
|
+
)
|
|
64
|
+
count: int = Field(default=1, description="Number of exposures to take with this configuration.")
|
|
65
|
+
image_type: ImageType = Field(
|
|
66
|
+
default=ImageType.OBJECT,
|
|
67
|
+
description="Type of image to take: OBJECT (science), BIAS, DARK, SKYFLAT, FOCUS, ACQUISITION, or GUIDING.",
|
|
68
|
+
)
|
|
69
|
+
binning: tuple[int, int] = Field(default=(1, 1), description="Detector binning as (x, y).")
|
|
70
|
+
window: tuple[int, int, int, int] | None = Field(
|
|
71
|
+
default=None,
|
|
72
|
+
description="Detector sub-window as (left, top, width, height). Uses the full frame if unset.",
|
|
73
|
+
)
|
|
74
|
+
optical_filter: str | None = Field(
|
|
75
|
+
default=None, description="Name of the filter to use. Uses the camera's current filter if unset."
|
|
76
|
+
)
|
|
61
77
|
|
|
62
78
|
async def get_exposure_time(self) -> float:
|
|
63
79
|
"""Return the exposure time, computing it dynamically if needed."""
|
|
@@ -69,22 +85,41 @@ class InstrumentConfig(BaseModel):
|
|
|
69
85
|
class Configuration(BaseModel):
|
|
70
86
|
model_config = ConfigDict(extra="forbid")
|
|
71
87
|
|
|
72
|
-
acquisition_config: AcquisitionConfig = Field(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
88
|
+
acquisition_config: AcquisitionConfig = Field(
|
|
89
|
+
default_factory=AcquisitionConfig, description="Settings for acquiring the target before exposing."
|
|
90
|
+
)
|
|
91
|
+
guiding_config: GuidingConfig = Field(
|
|
92
|
+
default_factory=GuidingConfig, description="Settings for auto-guiding while exposing."
|
|
93
|
+
)
|
|
94
|
+
instrument_configs: list[InstrumentConfig] = Field(
|
|
95
|
+
default_factory=lambda: [InstrumentConfig()],
|
|
96
|
+
description="Sequence of instrument configurations to run, in order, once per repeat.",
|
|
97
|
+
)
|
|
98
|
+
repeats: int = Field(
|
|
99
|
+
default=1, description="Number of times to repeat the full sequence of instrument configurations."
|
|
100
|
+
)
|
|
76
101
|
|
|
77
102
|
|
|
78
103
|
class ImagingScript(Script):
|
|
79
104
|
"""Default script for imaging configs."""
|
|
80
105
|
|
|
81
|
-
configuration: Configuration = Field(default_factory=Configuration)
|
|
82
|
-
|
|
83
|
-
camera: Annotated[str, ICamera, IBinning, IWindow, IExposureTime, IImageType]
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
106
|
+
configuration: Configuration = Field(default_factory=Configuration, description="What to expose and how.")
|
|
107
|
+
|
|
108
|
+
camera: Annotated[str, ICamera, IBinning, IWindow, IExposureTime, IImageType] = Field(
|
|
109
|
+
description="Name of the camera module to expose with."
|
|
110
|
+
)
|
|
111
|
+
telescope: Annotated[str | None, ITelescope, IPointingRaDec] = Field(
|
|
112
|
+
default=None, description="Name of the telescope module to point at the target. Required for OBJECT exposures."
|
|
113
|
+
)
|
|
114
|
+
filters: Annotated[str | None, IFilters] = Field(
|
|
115
|
+
default=None, description="Name of the filter wheel module. Required if any instrument config sets a filter."
|
|
116
|
+
)
|
|
117
|
+
autoguider: Annotated[str | None, IAutoGuiding] = Field(
|
|
118
|
+
default=None, description="Name of the auto-guiding module. Required if guiding is enabled."
|
|
119
|
+
)
|
|
120
|
+
acquisition: Annotated[str | None, IAcquisition] = Field(
|
|
121
|
+
default=None, description="Name of the acquisition module. Required if acquisition is enabled."
|
|
122
|
+
)
|
|
88
123
|
|
|
89
124
|
_object_name: str | None = PrivateAttr(default=None)
|
|
90
125
|
|
|
@@ -3,6 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
from typing import TYPE_CHECKING
|
|
5
5
|
|
|
6
|
+
from pydantic import Field
|
|
7
|
+
|
|
6
8
|
from pyobs.interfaces import FitsHeaderEntry
|
|
7
9
|
from pyobs.utils.serialization import PolymorphicBaseModel
|
|
8
10
|
from pyobs.utils.time import Time
|
|
@@ -14,7 +16,7 @@ log = logging.getLogger(__name__)
|
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
class Script(PolymorphicBaseModel):
|
|
17
|
-
exptime_done: float = 0.0
|
|
19
|
+
exptime_done: float = Field(default=0.0, description="Exposure time accumulated so far while running this script.")
|
|
18
20
|
|
|
19
21
|
_cant_run_reason: str | None = None
|
|
20
22
|
|
|
@@ -41,10 +41,12 @@ def _build_params_model(method, provided_keys):
|
|
|
41
41
|
class CallModuleScript(Script):
|
|
42
42
|
"""Script for calling a method on a module."""
|
|
43
43
|
|
|
44
|
-
module: str
|
|
45
|
-
interface: str
|
|
46
|
-
method: str
|
|
47
|
-
params: dict[str, str | int | float] = Field(
|
|
44
|
+
module: str = Field(description="Name of the module to call the method on.")
|
|
45
|
+
interface: str = Field(description="Full class path of the interface that declares `method`.")
|
|
46
|
+
method: str = Field(description="Name of the method to call.")
|
|
47
|
+
params: dict[str, str | int | float] = Field(
|
|
48
|
+
default_factory=dict, description="Keyword arguments to pass to the method, validated against its signature."
|
|
49
|
+
)
|
|
48
50
|
|
|
49
51
|
@model_validator(mode="after")
|
|
50
52
|
def _validate_params(self) -> CallModuleScript:
|
{pyobs_core-2.0.0.dev94 → pyobs_core-2.0.0.dev97}/pyobs/robotic/scripts/utils/debugtrigger.py
RENAMED
|
@@ -3,6 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
from typing import TYPE_CHECKING
|
|
5
5
|
|
|
6
|
+
from pydantic import Field
|
|
7
|
+
|
|
6
8
|
if TYPE_CHECKING:
|
|
7
9
|
from pyobs.robotic.task import TaskData
|
|
8
10
|
from pyobs.robotic.scripts import Script
|
|
@@ -13,7 +15,7 @@ log = logging.getLogger(__name__)
|
|
|
13
15
|
class DebugTriggerScript(Script):
|
|
14
16
|
"""Script for a debug trigger."""
|
|
15
17
|
|
|
16
|
-
triggered: bool = False
|
|
18
|
+
triggered: bool = Field(default=False, description="Set to True once this script has run.")
|
|
17
19
|
|
|
18
20
|
async def can_run(self, data: TaskData | None) -> bool:
|
|
19
21
|
return True
|
|
@@ -4,6 +4,8 @@ import logging
|
|
|
4
4
|
from datetime import UTC, datetime
|
|
5
5
|
from typing import TYPE_CHECKING
|
|
6
6
|
|
|
7
|
+
from pydantic import Field
|
|
8
|
+
|
|
7
9
|
if TYPE_CHECKING:
|
|
8
10
|
from pyobs.robotic.task import TaskData
|
|
9
11
|
from pyobs.robotic.scripts import Script
|
|
@@ -14,7 +16,7 @@ log = logging.getLogger(__name__)
|
|
|
14
16
|
class LogScript(Script):
|
|
15
17
|
"""Script for logging something."""
|
|
16
18
|
|
|
17
|
-
expression: str
|
|
19
|
+
expression: str = Field(description="Python expression to evaluate and log the value of.")
|
|
18
20
|
|
|
19
21
|
async def can_run(self, data: TaskData | None) -> bool:
|
|
20
22
|
return True
|
|
@@ -15,8 +15,8 @@ from pyobs.utils.time import Time
|
|
|
15
15
|
log = logging.getLogger(__name__)
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
class
|
|
19
|
-
"""Observation archive based on pyobs-
|
|
18
|
+
class PortalObservationArchive(ObservationArchive):
|
|
19
|
+
"""Observation archive based on pyobs-portal."""
|
|
20
20
|
|
|
21
21
|
def __init__(
|
|
22
22
|
self,
|
|
@@ -39,12 +39,12 @@ class BackendObservationArchive(ObservationArchive):
|
|
|
39
39
|
self.add_background_task(self._check_for_changes)
|
|
40
40
|
|
|
41
41
|
async def open(self) -> None:
|
|
42
|
-
"""Opens the
|
|
42
|
+
"""Opens the portal observation archive."""
|
|
43
43
|
self._aiohttp_session = aiohttp.ClientSession(headers={"Authorization": f"Token {self._token}"})
|
|
44
44
|
await ObservationArchive.open(self)
|
|
45
45
|
|
|
46
46
|
async def close(self) -> None:
|
|
47
|
-
"""Closes the
|
|
47
|
+
"""Closes the portal observation archive."""
|
|
48
48
|
await ObservationArchive.close(self)
|
|
49
49
|
if self._aiohttp_session is not None:
|
|
50
50
|
await self._aiohttp_session.close()
|
|
@@ -57,20 +57,20 @@ class BackendObservationArchive(ObservationArchive):
|
|
|
57
57
|
return self._aiohttp_session
|
|
58
58
|
|
|
59
59
|
async def _check_for_changes(self) -> None:
|
|
60
|
-
"""Update schedule in background, gated on the
|
|
60
|
+
"""Update schedule in background, gated on the portal's update marker."""
|
|
61
61
|
|
|
62
62
|
while True:
|
|
63
63
|
try:
|
|
64
64
|
await self._poll()
|
|
65
65
|
except Exception as e:
|
|
66
|
-
log.error("Failed to update observations from
|
|
66
|
+
log.error("Failed to update observations from portal: %s", e)
|
|
67
67
|
await asyncio.sleep(5)
|
|
68
68
|
|
|
69
69
|
async def _poll(self) -> None:
|
|
70
|
-
"""Re-download the schedule when the
|
|
70
|
+
"""Re-download the schedule when the portal's ``last_observation_update`` marker moved.
|
|
71
71
|
|
|
72
|
-
The marker is a DB-derived ``Max(updated_at)`` (pyobs-
|
|
73
|
-
gunicorn workers, so it is a safe refresh gate; see ``
|
|
72
|
+
The marker is a DB-derived ``Max(updated_at)`` (pyobs-portal#84), truthful across
|
|
73
|
+
gunicorn workers, so it is a safe refresh gate; see ``PortalTaskArchive._poll``. The
|
|
74
74
|
content comparison in :meth:`_update` still decides whether to fire ``on_tasks_changed``.
|
|
75
75
|
"""
|
|
76
76
|
last_update = await self.last_update_time()
|
|
@@ -79,12 +79,12 @@ class BackendObservationArchive(ObservationArchive):
|
|
|
79
79
|
self._last_marker = last_update
|
|
80
80
|
|
|
81
81
|
async def _update(self) -> None:
|
|
82
|
-
"""Fetch the schedule from the
|
|
82
|
+
"""Fetch the schedule from the portal and apply it if anything changed.
|
|
83
83
|
|
|
84
|
-
Called by :meth:`_poll` after the
|
|
84
|
+
Called by :meth:`_poll` after the portal marker moved (or on the first poll). Changes are
|
|
85
85
|
detected by comparing full observation contents via ``model_dump(use_task_id=True)``,
|
|
86
86
|
keyed by observation ID so a stable reordering of the same items is not mistaken for a
|
|
87
|
-
change: the
|
|
87
|
+
change: the portal serializes ``task`` as a plain FK ID, while cached copies get their
|
|
88
88
|
``task`` replaced by a full ``Task`` when the mastermind calls ``fetch_task()``, so the ID
|
|
89
89
|
normalization keeps both sides comparable. The comparison includes ``state``
|
|
90
90
|
(``Observation.__eq__`` ignores it), which matters for in-set transitions such as
|
|
@@ -265,4 +265,4 @@ class BackendObservationArchive(ObservationArchive):
|
|
|
265
265
|
return ObservationList([self.pyobs_model_validate(Observation, obs) for obs in observations])
|
|
266
266
|
|
|
267
267
|
|
|
268
|
-
__all__ = ["
|
|
268
|
+
__all__ = ["PortalObservationArchive"]
|
|
@@ -13,14 +13,14 @@ from pyobs.utils.time import Time
|
|
|
13
13
|
log = logging.getLogger(__name__)
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
class
|
|
17
|
-
"""Task archive based on pyobs-
|
|
16
|
+
class PortalTaskArchive(TaskArchive):
|
|
17
|
+
"""Task archive based on pyobs-portal."""
|
|
18
18
|
|
|
19
19
|
def __init__(self, url: str, token: str, auto_update: bool = True, **kwargs: Any):
|
|
20
20
|
"""Creates a new task archive.
|
|
21
21
|
|
|
22
22
|
Args:
|
|
23
|
-
url: URL of pyobs-
|
|
23
|
+
url: URL of pyobs-portal.
|
|
24
24
|
token: Auth token.
|
|
25
25
|
"""
|
|
26
26
|
TaskArchive.__init__(self, **kwargs)
|
|
@@ -36,12 +36,12 @@ class BackendTaskArchive(TaskArchive):
|
|
|
36
36
|
self.add_background_task(self._check_for_changes)
|
|
37
37
|
|
|
38
38
|
async def open(self) -> None:
|
|
39
|
-
"""Opens the
|
|
39
|
+
"""Opens the portal task archive."""
|
|
40
40
|
self._aiohttp_session = aiohttp.ClientSession(headers={"Authorization": f"Token {self._token}"})
|
|
41
41
|
await TaskArchive.open(self)
|
|
42
42
|
|
|
43
43
|
async def close(self) -> None:
|
|
44
|
-
"""Closes the
|
|
44
|
+
"""Closes the portal task archive."""
|
|
45
45
|
await TaskArchive.close(self)
|
|
46
46
|
if self._aiohttp_session is not None:
|
|
47
47
|
await self._aiohttp_session.close()
|
|
@@ -54,18 +54,18 @@ class BackendTaskArchive(TaskArchive):
|
|
|
54
54
|
return self._aiohttp_session
|
|
55
55
|
|
|
56
56
|
async def _check_for_changes(self) -> None:
|
|
57
|
-
"""Update tasks in background, gated on the
|
|
57
|
+
"""Update tasks in background, gated on the portal's update marker."""
|
|
58
58
|
while True:
|
|
59
59
|
try:
|
|
60
60
|
await self._poll()
|
|
61
61
|
except Exception as e:
|
|
62
|
-
log.error("Failed to update tasks from
|
|
62
|
+
log.error("Failed to update tasks from portal: %s", e)
|
|
63
63
|
await asyncio.sleep(5)
|
|
64
64
|
|
|
65
65
|
async def _poll(self) -> None:
|
|
66
|
-
"""Re-download tasks/projects when the
|
|
66
|
+
"""Re-download tasks/projects when the portal's ``last_task_update`` marker moved.
|
|
67
67
|
|
|
68
|
-
The marker is a DB-derived ``Max(updated_at)`` (pyobs-
|
|
68
|
+
The marker is a DB-derived ``Max(updated_at)`` (pyobs-portal#84), truthful across
|
|
69
69
|
gunicorn workers, so it is a safe refresh gate. Without it the archive re-downloaded (and
|
|
70
70
|
re-compared) on every poll, and the content comparison misfired whenever runtime code
|
|
71
71
|
mutated a serialized task field (e.g. ``DynamicTarget.resolve()`` overwriting ``name``),
|
|
@@ -78,14 +78,14 @@ class BackendTaskArchive(TaskArchive):
|
|
|
78
78
|
self._last_marker = last_update
|
|
79
79
|
|
|
80
80
|
async def _update(self) -> None:
|
|
81
|
-
"""Fetch tasks/projects from the
|
|
81
|
+
"""Fetch tasks/projects from the portal and apply them if anything changed.
|
|
82
82
|
|
|
83
|
-
Called by :meth:`_poll` after the
|
|
83
|
+
Called by :meth:`_poll` after the portal marker moved (or on the first poll); applies the
|
|
84
84
|
download only when the content actually differs from the cached copy. The comparison uses
|
|
85
85
|
``model_dump()`` rather than pydantic ``==``, which also compares runtime attributes (e.g.
|
|
86
86
|
``Task._cant_run_reason`` set by ``can_run()``) and would flag unchanged tasks as changed
|
|
87
87
|
on every poll; it is keyed by ID so that a stable reordering of the same items (e.g. an
|
|
88
|
-
unordered
|
|
88
|
+
unordered portal queryset) is not mistaken for a change.
|
|
89
89
|
"""
|
|
90
90
|
projects = await self._get_projects()
|
|
91
91
|
tasks = await self._get_tasks()
|
|
@@ -105,12 +105,12 @@ class BackendTaskArchive(TaskArchive):
|
|
|
105
105
|
return Time(res["last_task_update"])
|
|
106
106
|
|
|
107
107
|
async def _get_projects(self) -> list[Project]:
|
|
108
|
-
"""Fetch projects from
|
|
108
|
+
"""Fetch projects from portal."""
|
|
109
109
|
projects = await http_request_paginated(self._session, urljoin(self._url, "/api/projects/"), strict=True)
|
|
110
110
|
return [self.pyobs_model_validate(Project, project) for project in projects]
|
|
111
111
|
|
|
112
112
|
async def _get_tasks(self) -> list[Task]:
|
|
113
|
-
"""Fetch tasks from
|
|
113
|
+
"""Fetch tasks from portal."""
|
|
114
114
|
tasks = await http_request_paginated(self._session, urljoin(self._url, "/api/tasks/"), strict=True)
|
|
115
115
|
return [self.pyobs_model_validate(Task, task) for task in tasks]
|
|
116
116
|
|
|
@@ -118,7 +118,7 @@ class BackendTaskArchive(TaskArchive):
|
|
|
118
118
|
"""Returns time when last time any tasks changed (as observed by this archive).
|
|
119
119
|
|
|
120
120
|
This is the local time at which the last content change was detected by the polling loop,
|
|
121
|
-
not the
|
|
121
|
+
not the portal's marker timestamp -- the marker is per-process and unreliable.
|
|
122
122
|
"""
|
|
123
123
|
return self._last_update
|
|
124
124
|
|
|
@@ -151,4 +151,4 @@ class BackendTaskArchive(TaskArchive):
|
|
|
151
151
|
return None
|
|
152
152
|
|
|
153
153
|
|
|
154
|
-
__all__ = ["
|
|
154
|
+
__all__ = ["PortalTaskArchive"]
|
|
@@ -46,9 +46,9 @@ class Task(PolymorphicBaseModel):
|
|
|
46
46
|
script: dict[str, Any] = Field(default_factory=dict)
|
|
47
47
|
active: bool = True
|
|
48
48
|
updated_at: str | None = None
|
|
49
|
-
"""Last-modification timestamp as emitted by pyobs-
|
|
50
|
-
added in pyobs-
|
|
51
|
-
model (``extra="forbid"``) accepts the field the
|
|
49
|
+
"""Last-modification timestamp as emitted by pyobs-portal (DB-derived ``updated_at``,
|
|
50
|
+
added in pyobs-portal#84). Carried for round-trip fidelity so the strict ``Task``
|
|
51
|
+
model (``extra="forbid"``) accepts the field the portal now sends; not used by pyobs itself."""
|
|
52
52
|
|
|
53
53
|
_resolved_target: Target | None = PrivateAttr(default=None)
|
|
54
54
|
_cant_run_reason: str | None = None
|