pyobs-core 2.0.0.dev85__tar.gz → 2.0.0.dev87__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.dev85 → pyobs_core-2.0.0.dev87}/PKG-INFO +1 -1
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/xmpp/xmppcomm.py +31 -2
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/mixins/fitsheader.py +9 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/backend/observationarchive.py +34 -14
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/backend/taskarchive.py +33 -11
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/task.py +1 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/utils/archive/archive.py +2 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/utils/archive/local_archive.py +9 -2
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/utils/archive/pyobs_archive.py +7 -2
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/http.py +16 -2
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyproject.toml +1 -1
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/.gitignore +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/LICENSE +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/application.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/background_task.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/cli/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/cli/_cli.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/cli/pyobs.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/cli/pyobsd.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/cli/pyobsw.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/comm.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/commlogging.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/dummy/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/dummy/dummycomm.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/local/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/local/localcomm.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/local/localnetwork.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/proxy.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/xmpp/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/xmpp/rpc.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/xmpp/serializer.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/xmpp/xep_0009/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/xmpp/xep_0009/binding.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/xmpp/xep_0009/rpc.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/xmpp/xep_0009_timeout/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/xmpp/xep_0009_timeout/rpc.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/xmpp/xep_0009_timeout/stanza/RPC.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/xmpp/xep_0009_timeout/stanza/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/xmpp/xmppclient.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/events/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/events/badweather.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/events/event.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/events/exposurestatuschanged.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/events/filterchanged.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/events/focusfound.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/events/goodweather.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/events/log.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/events/modechanged.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/events/moduleclosed.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/events/moduleopened.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/events/motionstatuschanged.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/events/move.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/events/newimage.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/events/newspectrum.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/events/offsets.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/events/roofclosing.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/events/roofopened.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/events/taskfailed.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/events/taskfinished.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/events/taskstarted.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/events/testevent.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/image.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/meta/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/meta/altazoffsets.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/meta/exptime.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/meta/genericoffset.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/meta/onskydistance.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/meta/pixeloffsets.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/meta/radecoffsets.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/meta/skyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processor.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/_daobackgroundremover.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/annotation/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/annotation/_pillow.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/annotation/circle.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/annotation/crosshair.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/annotation/text.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/astrometry/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/astrometry/_dotnet_request.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/astrometry/_dotnet_request_builder.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/astrometry/_dotnet_request_logger.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/astrometry/_dotnet_response_saver.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/astrometry/astrometry.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/astrometry/dotnet.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/calibration/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/calibration/_calibration_cache.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/calibration/_ccddata_calibrator.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/calibration/calibration.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/detection/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/detection/_pysep_stats_calculator.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/detection/_source_catalog.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/detection/daophot.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/detection/pysep.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/detection/simpledisk.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/detection/sourcedetection.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/exptime/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/exptime/exptime.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/exptime/star.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/image/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/image/addfitsheaders.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/image/download.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/image/flip.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/image/grayscale.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/image/httpserver.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/image/normalize.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/image/save.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/image/saveimage.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/image/smooth.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/image/softbin.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/misc/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/misc/addmask.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/misc/catalogcircularmask.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/misc/circularmask.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/misc/createfilename.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/misc/imagesourcefilter.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/misc/removebackground.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/modules/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/modules/getfitsheaders.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/offsets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/offsets/astrometry.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/offsets/brighteststar.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/offsets/brighteststar_guiding.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/offsets/dummyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/offsets/dummyskyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/offsets/fitsheader.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/offsets/offsets.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/offsets/pixeloffsets.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/offsets/projected.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/offsets/spilled_light.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/photometry/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/photometry/_photometry_calculator.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/photometry/_photutil_aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/photometry/_sep_aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/photometry/aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/photometry/photometry.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/photometry/photutil.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/photometry/pysep.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/wcs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/wcs/solarhelioprojective.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IAbortable.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IAcquisition.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IAutoFocus.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IAutoGuiding.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IAutonomous.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IBinning.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/ICalibrate.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/ICamera.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IConfig.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/ICooling.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IData.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IDataSequence.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IDome.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IExposure.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IExposureTime.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IFilters.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IFitsHeaderAfter.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IFitsHeaderBefore.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IFlatField.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IFocusModel.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IFocuser.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IGain.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IImageFormat.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IImageType.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IMode.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IModule.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IMotion.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IMultiFiber.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IOffsetsAltAz.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IOffsetsRaDec.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IPointingAltAz.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IPointingBody.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IPointingHeliocentricPolar.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IPointingHeliographicStonyhurst.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IPointingHelioprojective.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IPointingOrbitalElements.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IPointingRaDec.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IPointingSeries.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IReady.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IRoof.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IRotation.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IRunnable.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IRunning.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IScriptRunner.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/ISpectrograph.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IStartStop.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IStructuredConfig.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/ISyncTarget.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/ITelescope.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/ITemperatures.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/ITrackingMode.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/ITrackingRate.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IVideo.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IWeather.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/IWindow.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/interfaces/interface.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/mixins/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/mixins/camerasettings.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/mixins/fitsnamespace.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/mixins/follow.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/mixins/motionstatus.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/mixins/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/mixins/waitformotion.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/mixins/weatheraware.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/camera/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/camera/adaptive.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/camera/basecamera.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/camera/basespectrograph.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/camera/basevideo.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/camera/dummycamera.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/camera/dummyspectrograph.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/camera/dummyvideo.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/camera/pipelinecamera.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/flatfield/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/flatfield/flatfield.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/flatfield/pointing.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/flatfield/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/focus/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/focus/dummyautofocus.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/focus/focusmodel.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/focus/focusseries.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/image/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/image/imagewatcher.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/image/imagewriter.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/image/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/image/seeing.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/module.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/pointing/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/pointing/_base.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/pointing/_baseguiding.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/pointing/acquisition.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/pointing/autoguiding.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/pointing/dummyacquisition.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/pointing/dummyguiding.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/pointing/guidingstatistics/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/pointing/guidingstatistics/guidingstatistics.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/pointing/guidingstatistics/pixeloffset.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/pointing/guidingstatistics/skyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/pointing/guidingstatistics/uptime.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/pointing/scienceframeguiding.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/robotic/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/robotic/mastermind.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/robotic/pointing.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/robotic/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/robotic/scriptrunner.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/roof/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/roof/basedome.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/roof/baseroof.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/roof/dummyroof.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/telescope/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/telescope/_dummytelescopebase.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/telescope/basetelescope.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/telescope/dummyaltaztelescope.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/telescope/dummyradectelescope.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/telescope/dummysolartelescope.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/test/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/test/standalone.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/utils/dummymode.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/utils/fluentlogger.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/utils/httpfilecache.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/utils/kiosk.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/utils/matrix.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/utils/stellarium.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/utils/telegram.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/utils/trigger.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/weather/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/weather/mockweather.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/weather/weather.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/weather/weather_api.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/modules/weather/weather_state.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/object.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/py.typed +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/observation.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/_executor.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/astroplanscheduler.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/constraints/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/constraints/airmassconstraint.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/constraints/constraint.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/constraints/moonilluminationconstraint.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/constraints/moonseparationconstraint.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/constraints/solarelevationconstraint.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/constraints/timeconstraint.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/dataprovider.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/merits/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/merits/aftertime.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/merits/beforetime.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/merits/constant.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/merits/follow.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/merits/interval.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/merits/merit.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/merits/pernight.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/merits/random.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/merits/timewindow.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/merits/transit.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/observationarchiveevolution.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/ondemandscheduler.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/targets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/targets/dynamictarget.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/targets/heliocentricpolartarget.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/targets/helioprojectivetarget.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/targets/picker/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/targets/picker/csvpicker.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/targets/picker/picker.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/targets/siderealtarget.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/targets/target.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scheduler/taskscheduler.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scripts/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scripts/calibration/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scripts/calibration/darkbias.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scripts/calibration/pointing.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scripts/calibration/skyflats.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scripts/control/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scripts/control/cases.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scripts/control/conditional.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scripts/control/parallel.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scripts/control/selector.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scripts/control/sequential.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scripts/exceptions.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scripts/imaging/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scripts/imaging/autofocus.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scripts/imaging/imaging.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scripts/imaging/transitimaging.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scripts/script.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scripts/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scripts/utils/callmodule.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scripts/utils/debugtrigger.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/scripts/utils/log.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/backend/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/filesystem/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/filesystem/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/filesystem/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/lco/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/lco/_portal.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/lco/_schedulereader.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/lco/_schedulewriter.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/lco/configdb.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/lco/mockobservationarchive.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/lco/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/lco/scripts/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/lco/scripts/autofocus.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/lco/scripts/default.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/lco/scripts/script.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/lco/task.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/lco/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/lco/taskrunner.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/memory/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/memory/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/memory/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/taskrunner.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/utils/archive/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/utils/exptime/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/utils/exptime/exptime.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/utils/exptime/stellarexptime.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/utils/skyflats/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/utils/skyflats/exptimeeval.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/utils/skyflats/flatfielder.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/utils/skyflats/pointing/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/utils/skyflats/pointing/base.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/utils/skyflats/pointing/static.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/utils/skyflats/priorities/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/utils/skyflats/priorities/archive.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/utils/skyflats/priorities/base.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/utils/skyflats/priorities/const.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/utils/skyflats/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/average.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/cache.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/config.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/config_schema.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/coordinates.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/curvefit.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/enums.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/exceptions.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/fits.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/focusseries/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/focusseries/base.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/focusseries/photometry.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/focusseries/projection.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/grids/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/grids/filters.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/grids/grid.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/grids/gridnode.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/grids/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/gui/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/gui/camera/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/gui/camera/binningwidget.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/gui/camera/datadisplaywidget.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/gui/camera/exposewidget.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/gui/camera/exposuretimewidget.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/gui/camera/imageformatwidget.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/gui/camera/listpickerdialog.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/gui/camera/windowingwidget.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/influxdb.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/logger.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/logging/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/logging/context.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/logging/resolvableerror.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/modulegui.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/offsets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/offsets/applyaltazoffsets.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/offsets/applyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/offsets/applyradecoffsets.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/parallel.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/pipeline/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/pipeline/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/pipeline/progress.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/pipeline/reduction.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/pipeline/reduction_base.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/publisher/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/publisher/csv.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/publisher/http.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/publisher/log.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/publisher/multi.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/publisher/publisher.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/serialization.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/shellcommand.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/threads/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/threads/lockwithabort.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/time.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/units.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/utils/versions.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/version.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/vfs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/vfs/archivefile.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/vfs/bufferedfile.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/vfs/file.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/vfs/filelists/__init__.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/vfs/filelists/filelist.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/vfs/filelists/testing.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/vfs/httpfile.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/vfs/localfile.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/vfs/memfile.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/vfs/sftpfile.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/vfs/smbfile.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/vfs/sshfile.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/vfs/tempfile.py +0 -0
- {pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/vfs/vfs.py +0 -0
|
@@ -60,6 +60,21 @@ def _retry_delay(attempt: int, cap: float = 30.0, base: float = 1.0) -> float:
|
|
|
60
60
|
return random.uniform(0, min(cap, base * (2**attempt)))
|
|
61
61
|
|
|
62
62
|
|
|
63
|
+
def _log_task_exception(task: asyncio.Task[Any]) -> None:
|
|
64
|
+
"""Retrieve and log a background task's exception, if it failed.
|
|
65
|
+
|
|
66
|
+
Results of asyncio.create_task() that are never awaited or callback-ed have their
|
|
67
|
+
exceptions reported by the event loop's default handler as "Task exception was never
|
|
68
|
+
retrieved" -- a noisy ERROR traceback that carries no context. Retrieving the exception
|
|
69
|
+
here turns that into a normal log line with the task's failure attached.
|
|
70
|
+
"""
|
|
71
|
+
if task.cancelled():
|
|
72
|
+
return
|
|
73
|
+
exc = task.exception()
|
|
74
|
+
if exc is not None:
|
|
75
|
+
log.error("Unhandled exception in XMPP event handler task", exc_info=exc)
|
|
76
|
+
|
|
77
|
+
|
|
63
78
|
# anchored at both ends -- re.match alone doesn't anchor the end, so e.g. "user@domain/res/extra"
|
|
64
79
|
# would otherwise still "match" as a valid prefix
|
|
65
80
|
_JID_RE = re.compile(r"([\w_\-\.]+)@([\w_\-\.]+)/([\w_\-\.]+)$")
|
|
@@ -979,7 +994,12 @@ class XmppComm(Comm):
|
|
|
979
994
|
for callback in callbacks:
|
|
980
995
|
callback(state_obj)
|
|
981
996
|
else:
|
|
982
|
-
|
|
997
|
+
# Non-state notifications are handled asynchronously. Attach a done-callback so the
|
|
998
|
+
# task's exception is retrieved: without it, a failure inside _handle_event is never
|
|
999
|
+
# retrieved and asyncio reports it as "Task exception was never retrieved" (see
|
|
1000
|
+
# _handle_event for the payload-less notification case that used to trigger this).
|
|
1001
|
+
task = asyncio.create_task(self._handle_event(msg, node))
|
|
1002
|
+
task.add_done_callback(_log_task_exception)
|
|
983
1003
|
|
|
984
1004
|
async def _handle_event(self, msg: Any, node: str) -> None:
|
|
985
1005
|
"""Handles an event.
|
|
@@ -994,7 +1014,16 @@ class XmppComm(Comm):
|
|
|
994
1014
|
# get body, unescape it, parse it
|
|
995
1015
|
# State-node messages are handled synchronously in _handle_event_sync
|
|
996
1016
|
# before this async task runs. By the time we get here it's a pyobs event.
|
|
997
|
-
|
|
1017
|
+
# Not every notification carries an item with a payload: retract stanzas,
|
|
1018
|
+
# node purges, and nodes with deliver_payloads off all arrive payload-less.
|
|
1019
|
+
# The state-node path copes via _fetch_and_dispatch_state; for events there is
|
|
1020
|
+
# nothing to refetch, so just drop the notification.
|
|
1021
|
+
items = msg["pubsub_event"]["items"]
|
|
1022
|
+
item = items["item"] if items is not None else None
|
|
1023
|
+
payload = item["payload"] if item is not None else None
|
|
1024
|
+
if payload is None or payload.text is None:
|
|
1025
|
+
return
|
|
1026
|
+
body = json.loads(xml.sax.saxutils.unescape(payload.text))
|
|
998
1027
|
|
|
999
1028
|
# do we have a <delay> element?
|
|
1000
1029
|
delay = msg.xml.findall("{urn:sleekxmpp:delay}delay")
|
|
@@ -135,6 +135,15 @@ class FitsHeaderMixin:
|
|
|
135
135
|
except exc.RemoteError as e:
|
|
136
136
|
log.warning("Could not fetch FITS headers from %s: %s.", client, str(e))
|
|
137
137
|
continue
|
|
138
|
+
except Exception as e:
|
|
139
|
+
# XmppComm.execute() only converts IqError/IqTimeout into RemoteError; anything
|
|
140
|
+
# else raised while making or deserializing the RPC call (e.g. a peer returning a
|
|
141
|
+
# malformed IFitsHeaderBefore/After response) escapes as a raw exception. That must
|
|
142
|
+
# not take down the whole exposure -- log and skip this peer's headers (#767).
|
|
143
|
+
log.warning(
|
|
144
|
+
"Could not fetch FITS headers from %s: unexpected %s: %s.", client, type(e).__name__, str(e)
|
|
145
|
+
)
|
|
146
|
+
continue
|
|
138
147
|
|
|
139
148
|
# add them to fits file
|
|
140
149
|
if headers:
|
|
@@ -60,23 +60,43 @@ class BackendObservationArchive(ObservationArchive):
|
|
|
60
60
|
|
|
61
61
|
while True:
|
|
62
62
|
try:
|
|
63
|
-
|
|
64
|
-
if self._last_update is None or self._last_update < last_update:
|
|
65
|
-
self._observations = await self._get_schedule()
|
|
66
|
-
sorted_obs = sorted(
|
|
67
|
-
filter(lambda o: o.state == ObservationState.PENDING, self._observations),
|
|
68
|
-
key=lambda o: o.start,
|
|
69
|
-
)
|
|
70
|
-
if len(sorted_obs) == 0:
|
|
71
|
-
log.info("Downloaded new schedule.")
|
|
72
|
-
else:
|
|
73
|
-
obs = sorted_obs[0]
|
|
74
|
-
log.info("Downloaded new schedule. Next observation is task %s at %s.", obs.task, obs.start)
|
|
75
|
-
self._last_update = last_update
|
|
63
|
+
await self._update()
|
|
76
64
|
except Exception as e:
|
|
77
65
|
log.error("Failed to update observations from backend: %s", e)
|
|
78
66
|
await asyncio.sleep(5)
|
|
79
67
|
|
|
68
|
+
async def _update(self) -> None:
|
|
69
|
+
"""Fetch the schedule from the backend and apply it if anything changed.
|
|
70
|
+
|
|
71
|
+
Re-fetches unconditionally on every poll instead of gating on the backend's
|
|
72
|
+
``last_observation_update`` marker (per-process Django ``LocMemCache``, unreliable across
|
|
73
|
+
gunicorn workers -- see ``BackendTaskArchive``). Changes are detected by comparing full
|
|
74
|
+
observation contents via ``model_dump(use_task_id=True)``, keyed by observation ID so a
|
|
75
|
+
stable reordering of the same items is not mistaken for a change: the backend serializes
|
|
76
|
+
``task`` as a plain FK ID, while cached copies get their ``task`` replaced by a full
|
|
77
|
+
``Task`` when the mastermind calls ``fetch_task()``, so the ID normalization keeps both
|
|
78
|
+
sides comparable. The comparison includes ``state`` (``Observation.__eq__`` ignores it),
|
|
79
|
+
which matters for in-set transitions such as ``pending`` -> ``in_progress``; observations
|
|
80
|
+
leaving the fetched set -- e.g. ``window_expired``, which the server-side ``state``/
|
|
81
|
+
``end_after`` filters drop -- are picked up as list shrinkage by the unconditional
|
|
82
|
+
refetch.
|
|
83
|
+
"""
|
|
84
|
+
observations = await self._get_schedule()
|
|
85
|
+
if {o.id: o.model_dump(use_task_id=True) for o in observations} != {
|
|
86
|
+
o.id: o.model_dump(use_task_id=True) for o in self._observations
|
|
87
|
+
}:
|
|
88
|
+
self._observations = observations
|
|
89
|
+
self._last_update = Time.now()
|
|
90
|
+
sorted_obs = sorted(
|
|
91
|
+
filter(lambda o: o.state == ObservationState.PENDING, self._observations),
|
|
92
|
+
key=lambda o: o.start,
|
|
93
|
+
)
|
|
94
|
+
if len(sorted_obs) == 0:
|
|
95
|
+
log.info("Downloaded new schedule.")
|
|
96
|
+
else:
|
|
97
|
+
obs = sorted_obs[0]
|
|
98
|
+
log.info("Downloaded new schedule. Next observation is task %s at %s.", obs.task, obs.start)
|
|
99
|
+
|
|
80
100
|
async def last_update_time(self) -> Time:
|
|
81
101
|
"""Fetches last schedule update time."""
|
|
82
102
|
res = await http_request_with_retries(self._session, urljoin(self._url, "/api/last_observation_update/"))
|
|
@@ -229,7 +249,7 @@ class BackendObservationArchive(ObservationArchive):
|
|
|
229
249
|
params["end_before"] = end_before.isot
|
|
230
250
|
if end_after is not None:
|
|
231
251
|
params["end_after"] = end_after.isot
|
|
232
|
-
observations = await http_request_paginated(self._session, url, params=params)
|
|
252
|
+
observations = await http_request_paginated(self._session, url, params=params, strict=True)
|
|
233
253
|
return ObservationList([self.pyobs_model_validate(Observation, obs) for obs in observations])
|
|
234
254
|
|
|
235
255
|
|
{pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/storage/backend/taskarchive.py
RENAMED
|
@@ -56,18 +56,36 @@ class BackendTaskArchive(TaskArchive):
|
|
|
56
56
|
"""Update tasks in background."""
|
|
57
57
|
while True:
|
|
58
58
|
try:
|
|
59
|
-
|
|
60
|
-
if self._last_update is None or self._last_update < last_update:
|
|
61
|
-
self._projects = await self._get_projects()
|
|
62
|
-
self._tasks = await self._get_tasks()
|
|
63
|
-
log.info("Downloaded new tasks/projects.")
|
|
64
|
-
self._last_update = last_update
|
|
65
|
-
if self._on_tasks_changed is not None:
|
|
66
|
-
await self._on_tasks_changed()
|
|
59
|
+
await self._update()
|
|
67
60
|
except Exception as e:
|
|
68
61
|
log.error("Failed to update tasks from backend: %s", e)
|
|
69
62
|
await asyncio.sleep(5)
|
|
70
63
|
|
|
64
|
+
async def _update(self) -> None:
|
|
65
|
+
"""Fetch tasks/projects from the backend and apply them if anything changed.
|
|
66
|
+
|
|
67
|
+
Re-fetches unconditionally on every poll instead of gating on the backend's
|
|
68
|
+
``last_task_update`` marker: that marker is computed from a per-process Django
|
|
69
|
+
``LocMemCache`` and is unreliable across gunicorn workers, so gating on it let the
|
|
70
|
+
mastermind run stale tasks forever. Real changes are detected by comparing the downloaded
|
|
71
|
+
content against the cached copy. The comparison uses ``model_dump()`` rather than pydantic
|
|
72
|
+
``==``, which also compares runtime attributes (e.g. ``Task._cant_run_reason`` set by
|
|
73
|
+
``can_run()``) and would flag unchanged tasks as changed on every poll; it is keyed by ID
|
|
74
|
+
so that a stable reordering of the same items (e.g. an unordered backend queryset) is not
|
|
75
|
+
mistaken for a change.
|
|
76
|
+
"""
|
|
77
|
+
projects = await self._get_projects()
|
|
78
|
+
tasks = await self._get_tasks()
|
|
79
|
+
if {p.code: p.model_dump() for p in projects} != {p.code: p.model_dump() for p in self._projects} or {
|
|
80
|
+
t.id: t.model_dump() for t in tasks
|
|
81
|
+
} != {t.id: t.model_dump() for t in self._tasks}:
|
|
82
|
+
self._projects = projects
|
|
83
|
+
self._tasks = tasks
|
|
84
|
+
self._last_update = Time.now()
|
|
85
|
+
log.info("Downloaded new tasks/projects.")
|
|
86
|
+
if self._on_tasks_changed is not None:
|
|
87
|
+
await self._on_tasks_changed()
|
|
88
|
+
|
|
71
89
|
async def last_update_time(self) -> Time:
|
|
72
90
|
"""Fetches last schedule update time."""
|
|
73
91
|
res = await http_request_with_retries(self._session, urljoin(self._url, "/api/last_task_update/"))
|
|
@@ -75,16 +93,20 @@ class BackendTaskArchive(TaskArchive):
|
|
|
75
93
|
|
|
76
94
|
async def _get_projects(self) -> list[Project]:
|
|
77
95
|
"""Fetch projects from backend."""
|
|
78
|
-
projects = await http_request_paginated(self._session, urljoin(self._url, "/api/projects/"))
|
|
96
|
+
projects = await http_request_paginated(self._session, urljoin(self._url, "/api/projects/"), strict=True)
|
|
79
97
|
return [self.pyobs_model_validate(Project, project) for project in projects]
|
|
80
98
|
|
|
81
99
|
async def _get_tasks(self) -> list[Task]:
|
|
82
100
|
"""Fetch tasks from backend."""
|
|
83
|
-
tasks = await http_request_paginated(self._session, urljoin(self._url, "/api/tasks/"))
|
|
101
|
+
tasks = await http_request_paginated(self._session, urljoin(self._url, "/api/tasks/"), strict=True)
|
|
84
102
|
return [self.pyobs_model_validate(Task, task) for task in tasks]
|
|
85
103
|
|
|
86
104
|
async def last_changed(self) -> Time | None:
|
|
87
|
-
"""Returns time when last time any tasks changed.
|
|
105
|
+
"""Returns time when last time any tasks changed (as observed by this archive).
|
|
106
|
+
|
|
107
|
+
This is the local time at which the last content change was detected by the polling loop,
|
|
108
|
+
not the backend's marker timestamp -- the marker is per-process and unreliable.
|
|
109
|
+
"""
|
|
88
110
|
return self._last_update
|
|
89
111
|
|
|
90
112
|
async def get_projects(self) -> list[Project]:
|
|
@@ -150,6 +150,7 @@ class Project(BaseModel):
|
|
|
150
150
|
name: str = ""
|
|
151
151
|
priority: float | None = Field(ge=0.0, le=9999.0, default=1.0)
|
|
152
152
|
users: list[str] = Field(default_factory=list)
|
|
153
|
+
public: bool = False # ingest backend `public` flag; default keeps old backends valid
|
|
153
154
|
|
|
154
155
|
|
|
155
156
|
__all__ = ["Task", "TaskData", "Project"]
|
|
@@ -42,6 +42,7 @@ class Archive(PolymorphicBaseModel, metaclass=ABCMeta):
|
|
|
42
42
|
binning: str | None = None,
|
|
43
43
|
filter_name: str | None = None,
|
|
44
44
|
rlevel: int | None = None,
|
|
45
|
+
obsnum: str | None = None,
|
|
45
46
|
) -> dict[str, list[Any]]: ...
|
|
46
47
|
|
|
47
48
|
@abstractmethod
|
|
@@ -57,6 +58,7 @@ class Archive(PolymorphicBaseModel, metaclass=ABCMeta):
|
|
|
57
58
|
binning: str | None = None,
|
|
58
59
|
filter_name: str | None = None,
|
|
59
60
|
rlevel: int | None = None,
|
|
61
|
+
obsnum: str | None = None,
|
|
60
62
|
) -> list[FrameInfo]: ...
|
|
61
63
|
|
|
62
64
|
@abstractmethod
|
{pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/utils/archive/local_archive.py
RENAMED
|
@@ -48,6 +48,7 @@ class LocalArchive(Archive):
|
|
|
48
48
|
"site",
|
|
49
49
|
"telescope",
|
|
50
50
|
"rlevel",
|
|
51
|
+
"obsnum",
|
|
51
52
|
]
|
|
52
53
|
}
|
|
53
54
|
for filename in filenames:
|
|
@@ -61,6 +62,7 @@ class LocalArchive(Archive):
|
|
|
61
62
|
columns["site"].append(hdr["SITEID"] if "SITEID" in hdr else None)
|
|
62
63
|
columns["telescope"].append(hdr["TELID"] if "TELID" in hdr else None)
|
|
63
64
|
columns["rlevel"].append(hdr["RLEVEL"] if "RLEVEL" in hdr else None)
|
|
65
|
+
columns["obsnum"].append(str(hdr["OBSNUM"]) if "OBSNUM" in hdr else None)
|
|
64
66
|
columns["filename"] = filenames
|
|
65
67
|
self._data = pd.DataFrame(columns)
|
|
66
68
|
|
|
@@ -76,6 +78,7 @@ class LocalArchive(Archive):
|
|
|
76
78
|
binning: str | None = None,
|
|
77
79
|
filter_name: str | None = None,
|
|
78
80
|
rlevel: int | None = None,
|
|
81
|
+
obsnum: str | None = None,
|
|
79
82
|
) -> pd.DataFrame:
|
|
80
83
|
data = self._data
|
|
81
84
|
if start is not None:
|
|
@@ -98,6 +101,8 @@ class LocalArchive(Archive):
|
|
|
98
101
|
data = data[data["filter"] == filter_name]
|
|
99
102
|
if rlevel is not None:
|
|
100
103
|
data = data[data["rlevel"] == rlevel]
|
|
104
|
+
if obsnum is not None:
|
|
105
|
+
data = data[data["obsnum"] == obsnum]
|
|
101
106
|
return data
|
|
102
107
|
|
|
103
108
|
async def list_options(
|
|
@@ -112,9 +117,10 @@ class LocalArchive(Archive):
|
|
|
112
117
|
binning: str | None = None,
|
|
113
118
|
filter_name: str | None = None,
|
|
114
119
|
rlevel: int | None = None,
|
|
120
|
+
obsnum: str | None = None,
|
|
115
121
|
) -> dict[str, list[Any]]:
|
|
116
122
|
data = self._filter_data(
|
|
117
|
-
start, end, night, site, telescope, instrument, image_type, binning, filter_name, rlevel
|
|
123
|
+
start, end, night, site, telescope, instrument, image_type, binning, filter_name, rlevel, obsnum=obsnum
|
|
118
124
|
)
|
|
119
125
|
return {
|
|
120
126
|
"binnings": list(data["binning"].unique()),
|
|
@@ -137,9 +143,10 @@ class LocalArchive(Archive):
|
|
|
137
143
|
binning: str | None = None,
|
|
138
144
|
filter_name: str | None = None,
|
|
139
145
|
rlevel: int | None = None,
|
|
146
|
+
obsnum: str | None = None,
|
|
140
147
|
) -> list[FrameInfo]:
|
|
141
148
|
data = self._filter_data(
|
|
142
|
-
start, end, night, site, telescope, instrument, image_type, binning, filter_name, rlevel
|
|
149
|
+
start, end, night, site, telescope, instrument, image_type, binning, filter_name, rlevel, obsnum=obsnum
|
|
143
150
|
)
|
|
144
151
|
infos: list[FrameInfo] = []
|
|
145
152
|
for _, row in data.iterrows():
|
{pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/robotic/utils/archive/pyobs_archive.py
RENAMED
|
@@ -68,10 +68,11 @@ class PyobsArchive(Archive):
|
|
|
68
68
|
binning: str | None = None,
|
|
69
69
|
filter_name: str | None = None,
|
|
70
70
|
rlevel: int | None = None,
|
|
71
|
+
obsnum: str | None = None,
|
|
71
72
|
) -> dict[str, list[Any]]:
|
|
72
73
|
url = urllib.parse.urljoin(self.url, "frames/aggregate/")
|
|
73
74
|
params = self._build_query(
|
|
74
|
-
start, end, night, site, telescope, instrument, image_type, binning, filter_name, rlevel
|
|
75
|
+
start, end, night, site, telescope, instrument, image_type, binning, filter_name, rlevel, obsnum=obsnum
|
|
75
76
|
)
|
|
76
77
|
async with aiohttp.ClientSession() as session:
|
|
77
78
|
async with session.get(url, params=params, headers=self._headers, timeout=self._timeout) as response:
|
|
@@ -91,10 +92,11 @@ class PyobsArchive(Archive):
|
|
|
91
92
|
binning: str | None = None,
|
|
92
93
|
filter_name: str | None = None,
|
|
93
94
|
rlevel: int | None = None,
|
|
95
|
+
obsnum: str | None = None,
|
|
94
96
|
) -> list[FrameInfo]:
|
|
95
97
|
url = urllib.parse.urljoin(self.url, "frames/")
|
|
96
98
|
params = self._build_query(
|
|
97
|
-
start, end, night, site, telescope, instrument, image_type, binning, filter_name, rlevel
|
|
99
|
+
start, end, night, site, telescope, instrument, image_type, binning, filter_name, rlevel, obsnum=obsnum
|
|
98
100
|
)
|
|
99
101
|
frames: list[FrameInfo] = []
|
|
100
102
|
params["offset"] = 0
|
|
@@ -123,6 +125,7 @@ class PyobsArchive(Archive):
|
|
|
123
125
|
binning: str | None = None,
|
|
124
126
|
filter_name: str | None = None,
|
|
125
127
|
rlevel: int | None = None,
|
|
128
|
+
obsnum: str | None = None,
|
|
126
129
|
) -> dict[str, Any]:
|
|
127
130
|
params: dict[str, Any] = {}
|
|
128
131
|
if start is not None:
|
|
@@ -145,6 +148,8 @@ class PyobsArchive(Archive):
|
|
|
145
148
|
params["FILTER"] = filter_name
|
|
146
149
|
if rlevel is not None:
|
|
147
150
|
params["RLEVEL"] = rlevel
|
|
151
|
+
if obsnum is not None:
|
|
152
|
+
params["OBSNUM"] = obsnum
|
|
148
153
|
return params
|
|
149
154
|
|
|
150
155
|
async def download_frames(self, infos: list[FrameInfo]) -> list[Image]:
|
|
@@ -46,13 +46,20 @@ async def http_request_with_retries(
|
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
async def http_request_paginated(
|
|
49
|
-
session: aiohttp.ClientSession,
|
|
49
|
+
session: aiohttp.ClientSession,
|
|
50
|
+
url: str,
|
|
51
|
+
method: str = "get",
|
|
52
|
+
expected_status: int = 200,
|
|
53
|
+
strict: bool = False,
|
|
54
|
+
**kwargs: Any,
|
|
50
55
|
) -> list[dict[str, Any]]:
|
|
51
56
|
"""Fetches all pages of a DRF-style paginated list endpoint and returns the combined results.
|
|
52
57
|
|
|
53
58
|
If a page beyond the first becomes invalid mid-fetch (DRF's "Invalid page." 404, which can
|
|
54
59
|
happen when concurrent writes shift page boundaries on a live-growing dataset), pagination
|
|
55
|
-
stops early with whatever was already fetched instead of failing the whole request.
|
|
60
|
+
stops early with whatever was already fetched instead of failing the whole request. With
|
|
61
|
+
``strict=True`` that truncation is raised as an error instead, so callers that treat the
|
|
62
|
+
result as authoritative (e.g. replacing a cached list) never apply a partial result silently.
|
|
56
63
|
"""
|
|
57
64
|
results: list[dict[str, Any]] = []
|
|
58
65
|
next_url: str | None = url
|
|
@@ -69,6 +76,13 @@ async def http_request_paginated(
|
|
|
69
76
|
and isinstance(e.body, dict)
|
|
70
77
|
and e.body.get("detail") == "Invalid page."
|
|
71
78
|
):
|
|
79
|
+
if strict:
|
|
80
|
+
log.warning(
|
|
81
|
+
"Pagination page became invalid mid-fetch, raising instead of returning a "
|
|
82
|
+
"truncated result of %d item(s).",
|
|
83
|
+
len(results),
|
|
84
|
+
)
|
|
85
|
+
raise
|
|
72
86
|
log.warning("Pagination page became invalid mid-fetch, stopping early with %d result(s).", len(results))
|
|
73
87
|
break
|
|
74
88
|
raise
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/xmpp/xep_0009_timeout/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/comm/xmpp/xep_0009_timeout/stanza/RPC.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/_daobackgroundremover.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/annotation/__init__.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/annotation/_pillow.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/annotation/circle.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/annotation/crosshair.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/annotation/text.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/astrometry/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/astrometry/astrometry.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/astrometry/dotnet.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/calibration/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/calibration/calibration.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/detection/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/detection/daophot.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/detection/pysep.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/detection/simpledisk.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/exptime/__init__.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev85 → pyobs_core-2.0.0.dev87}/pyobs/images/processors/exptime/exptime.py
RENAMED
|
File without changes
|
|
File without changes
|