pyobs-core 2.0.0.dev48__tar.gz → 2.0.0.dev49__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.dev48 → pyobs_core-2.0.0.dev49}/PKG-INFO +2 -2
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/application.py +130 -61
- pyobs_core-2.0.0.dev49/pyobs/comm/xmpp/__init__.py +3 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/comm/xmpp/xmppcomm.py +24 -4
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyproject.toml +2 -2
- pyobs_core-2.0.0.dev48/pyobs/comm/xmpp/__init__.py +0 -3
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/.gitignore +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/LICENSE +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/background_task.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/cli/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/cli/_cli.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/cli/pyobs.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/cli/pyobsd.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/cli/pyobsw.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/comm/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/comm/comm.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/comm/commlogging.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/comm/dummy/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/comm/dummy/dummycomm.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/comm/local/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/comm/local/localcomm.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/comm/local/localnetwork.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/comm/proxy.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/comm/xmpp/rpc.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/comm/xmpp/serializer.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/comm/xmpp/xep_0009/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/comm/xmpp/xep_0009/binding.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/comm/xmpp/xep_0009/rpc.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/comm/xmpp/xep_0009_timeout/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/comm/xmpp/xep_0009_timeout/rpc.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/comm/xmpp/xep_0009_timeout/stanza/RPC.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/comm/xmpp/xep_0009_timeout/stanza/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/comm/xmpp/xmppclient.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/events/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/events/badweather.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/events/event.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/events/exposurestatuschanged.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/events/filterchanged.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/events/focusfound.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/events/goodweather.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/events/log.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/events/modechanged.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/events/moduleclosed.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/events/moduleopened.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/events/motionstatuschanged.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/events/move.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/events/newimage.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/events/newspectrum.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/events/offsets.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/events/roofclosing.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/events/roofopened.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/events/taskfailed.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/events/taskfinished.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/events/taskstarted.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/events/testevent.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/image.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/meta/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/meta/altazoffsets.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/meta/exptime.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/meta/genericoffset.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/meta/onskydistance.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/meta/pixeloffsets.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/meta/radecoffsets.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/meta/skyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processor.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/_daobackgroundremover.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/annotation/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/annotation/_pillow.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/annotation/circle.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/annotation/crosshair.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/annotation/text.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/astrometry/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/astrometry/_dotnet_request.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/astrometry/_dotnet_request_builder.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/astrometry/_dotnet_request_logger.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/astrometry/_dotnet_response_saver.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/astrometry/astrometry.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/astrometry/dotnet.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/calibration/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/calibration/_calibration_cache.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/calibration/_ccddata_calibrator.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/calibration/calibration.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/detection/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/detection/_pysep_stats_calculator.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/detection/_source_catalog.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/detection/daophot.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/detection/pysep.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/detection/simpledisk.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/detection/sourcedetection.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/exptime/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/exptime/exptime.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/exptime/star.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/image/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/image/addfitsheaders.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/image/download.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/image/flip.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/image/grayscale.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/image/httpserver.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/image/normalize.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/image/save.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/image/saveimage.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/image/smooth.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/image/softbin.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/misc/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/misc/addmask.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/misc/catalogcircularmask.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/misc/circularmask.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/misc/createfilename.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/misc/imagesourcefilter.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/misc/removebackground.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/modules/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/modules/getfitsheaders.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/offsets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/offsets/astrometry.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/offsets/brighteststar.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/offsets/brighteststar_guiding.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/offsets/dummyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/offsets/dummyskyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/offsets/fitsheader.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/offsets/offsets.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/offsets/pixeloffsets.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/offsets/projected.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/offsets/spilled_light.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/photometry/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/photometry/_photometry_calculator.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/photometry/_photutil_aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/photometry/_sep_aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/photometry/aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/photometry/photometry.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/photometry/photutil.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/photometry/pysep.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/wcs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/wcs/solarhelioprojective.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IAbortable.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IAcquisition.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IAutoFocus.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IAutoGuiding.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IAutonomous.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IBinning.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/ICalibrate.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/ICamera.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IConfig.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/ICooling.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IData.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IDataSequence.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IDome.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IExposure.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IExposureTime.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IFilters.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IFitsHeaderAfter.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IFitsHeaderBefore.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IFlatField.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IFocusModel.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IFocuser.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IGain.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IImageFormat.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IImageType.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IMode.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IModule.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IMotion.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IMultiFiber.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IOffsetsAltAz.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IOffsetsRaDec.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IPointingAltAz.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IPointingBody.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IPointingHeliocentricPolar.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IPointingHeliographicStonyhurst.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IPointingHelioprojective.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IPointingOrbitalElements.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IPointingRaDec.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IPointingSeries.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IReady.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IRoof.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IRotation.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IRunnable.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IRunning.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IScriptRunner.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/ISpectrograph.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IStartStop.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IStructuredConfig.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/ISyncTarget.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/ITelescope.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/ITemperatures.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/ITrackingMode.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/ITrackingRate.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IVideo.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IWeather.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/IWindow.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/interfaces/interface.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/mixins/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/mixins/camerasettings.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/mixins/fitsheader.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/mixins/fitsnamespace.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/mixins/follow.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/mixins/motionstatus.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/mixins/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/mixins/waitformotion.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/mixins/weatheraware.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/camera/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/camera/adaptive.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/camera/basecamera.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/camera/basespectrograph.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/camera/basevideo.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/camera/dummycamera.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/camera/dummyspectrograph.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/camera/dummyvideo.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/camera/pipelinecamera.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/flatfield/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/flatfield/flatfield.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/flatfield/pointing.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/flatfield/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/focus/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/focus/dummyautofocus.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/focus/focusmodel.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/focus/focusseries.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/image/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/image/imagewatcher.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/image/imagewriter.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/image/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/image/seeing.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/module.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/pointing/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/pointing/_base.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/pointing/_baseguiding.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/pointing/acquisition.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/pointing/autoguiding.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/pointing/dummyacquisition.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/pointing/dummyguiding.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/pointing/guidingstatistics/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/pointing/guidingstatistics/guidingstatistics.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/pointing/guidingstatistics/pixeloffset.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/pointing/guidingstatistics/skyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/pointing/guidingstatistics/uptime.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/pointing/scienceframeguiding.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/robotic/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/robotic/mastermind.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/robotic/pointing.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/robotic/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/robotic/scriptrunner.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/roof/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/roof/basedome.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/roof/baseroof.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/roof/dummyroof.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/telescope/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/telescope/_dummytelescopebase.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/telescope/basetelescope.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/telescope/dummyaltaztelescope.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/telescope/dummyradectelescope.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/telescope/dummysolartelescope.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/test/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/test/standalone.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/utils/dummymode.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/utils/fluentlogger.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/utils/httpfilecache.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/utils/kiosk.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/utils/matrix.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/utils/stellarium.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/utils/telegram.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/utils/trigger.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/weather/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/weather/mockweather.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/weather/weather.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/weather/weather_api.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/modules/weather/weather_state.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/object.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/py.typed +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/observation.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/astroplanscheduler.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/constraints/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/constraints/airmassconstraint.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/constraints/constraint.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/constraints/moonilluminationconstraint.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/constraints/moonseparationconstraint.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/constraints/solarelevationconstraint.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/constraints/timeconstraint.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/dataprovider.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/merits/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/merits/aftertime.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/merits/beforetime.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/merits/constant.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/merits/follow.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/merits/interval.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/merits/merit.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/merits/pernight.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/merits/random.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/merits/timewindow.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/merits/transit.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/observationarchiveevolution.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/ondemandscheduler.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/targets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/targets/dynamictarget.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/targets/heliocentricpolartarget.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/targets/helioprojectivetarget.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/targets/picker/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/targets/picker/csvpicker.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/targets/picker/picker.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/targets/siderealtarget.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/targets/target.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scheduler/taskscheduler.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scripts/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scripts/calibration/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scripts/calibration/darkbias.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scripts/calibration/pointing.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scripts/calibration/skyflats.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scripts/control/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scripts/control/cases.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scripts/control/conditional.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scripts/control/parallel.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scripts/control/selector.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scripts/control/sequential.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scripts/exceptions.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scripts/imaging/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scripts/imaging/autofocus.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scripts/imaging/imaging.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scripts/imaging/transitimaging.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scripts/script.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scripts/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scripts/utils/callmodule.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scripts/utils/debugtrigger.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/scripts/utils/log.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/backend/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/backend/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/backend/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/filesystem/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/filesystem/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/filesystem/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/lco/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/lco/_portal.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/lco/_schedulereader.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/lco/_schedulewriter.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/lco/configdb.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/lco/mockobservationarchive.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/lco/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/lco/scripts/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/lco/scripts/autofocus.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/lco/scripts/default.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/lco/scripts/script.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/lco/task.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/lco/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/lco/taskrunner.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/memory/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/memory/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/memory/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/storage/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/task.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/taskrunner.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/utils/archive/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/utils/archive/archive.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/utils/archive/local_archive.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/utils/archive/pyobs_archive.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/utils/exptime/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/utils/exptime/exptime.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/utils/exptime/stellarexptime.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/utils/skyflats/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/utils/skyflats/exptimeeval.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/utils/skyflats/flatfielder.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/utils/skyflats/pointing/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/utils/skyflats/pointing/base.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/utils/skyflats/pointing/static.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/utils/skyflats/priorities/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/utils/skyflats/priorities/archive.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/utils/skyflats/priorities/base.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/utils/skyflats/priorities/const.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/robotic/utils/skyflats/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/average.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/cache.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/config.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/config_schema.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/coordinates.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/curvefit.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/enums.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/exceptions.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/fits.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/focusseries/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/focusseries/base.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/focusseries/photometry.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/focusseries/projection.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/grids/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/grids/filters.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/grids/grid.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/grids/gridnode.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/grids/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/gui/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/gui/camera/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/gui/camera/binningwidget.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/gui/camera/datadisplaywidget.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/gui/camera/exposewidget.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/gui/camera/exposuretimewidget.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/gui/camera/imageformatwidget.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/gui/camera/listpickerdialog.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/gui/camera/windowingwidget.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/http.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/influxdb.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/logger.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/logging/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/logging/context.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/logging/resolvableerror.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/modulegui.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/offsets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/offsets/applyaltazoffsets.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/offsets/applyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/offsets/applyradecoffsets.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/parallel.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/pipeline/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/pipeline/night.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/pipeline/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/publisher/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/publisher/csv.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/publisher/http.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/publisher/log.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/publisher/multi.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/publisher/publisher.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/serialization.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/shellcommand.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/threads/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/threads/lockwithabort.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/time.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/utils/units.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/version.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/vfs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/vfs/archivefile.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/vfs/bufferedfile.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/vfs/file.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/vfs/filelists/__init__.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/vfs/filelists/filelist.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/vfs/filelists/testing.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/vfs/httpfile.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/vfs/localfile.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/vfs/memfile.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/vfs/sftpfile.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/vfs/smbfile.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/vfs/sshfile.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/vfs/tempfile.py +0 -0
- {pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/vfs/vfs.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyobs-core
|
|
3
|
-
Version: 2.0.0.
|
|
3
|
+
Version: 2.0.0.dev49
|
|
4
4
|
Summary: robotic telescope software
|
|
5
5
|
Author-email: Tim-Oliver Husser <thusser@uni-goettingen.de>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -20,7 +20,7 @@ Requires-Dist: logging-journald>=0.6.11
|
|
|
20
20
|
Requires-Dist: numpy<3,>=2.2.5
|
|
21
21
|
Requires-Dist: pandas>=2.2.3
|
|
22
22
|
Requires-Dist: paramiko>=3.5.1
|
|
23
|
-
Requires-Dist: pillow>=
|
|
23
|
+
Requires-Dist: pillow>=12.3.0
|
|
24
24
|
Requires-Dist: psutil>=7.2.2
|
|
25
25
|
Requires-Dist: py-expression-eval<0.4,>=0.3.14
|
|
26
26
|
Requires-Dist: pydantic>=2.12.5
|
|
@@ -5,6 +5,7 @@ import os
|
|
|
5
5
|
import platform
|
|
6
6
|
import signal
|
|
7
7
|
import warnings
|
|
8
|
+
from collections.abc import Awaitable, Callable
|
|
8
9
|
from io import StringIO
|
|
9
10
|
from typing import Any, TypedDict
|
|
10
11
|
|
|
@@ -56,7 +57,9 @@ class Application:
|
|
|
56
57
|
|
|
57
58
|
def __init__(
|
|
58
59
|
self,
|
|
59
|
-
config: str,
|
|
60
|
+
config: str | None = None,
|
|
61
|
+
module_factory: Callable[[], Awaitable[Module]] | None = None,
|
|
62
|
+
loop_module_class: type[Module] | None = None,
|
|
60
63
|
log_file: str | None = None,
|
|
61
64
|
log_level: str = "info",
|
|
62
65
|
syslog: bool = False,
|
|
@@ -65,18 +68,36 @@ class Application:
|
|
|
65
68
|
):
|
|
66
69
|
"""Initializes a pyobs application.
|
|
67
70
|
|
|
71
|
+
Exactly one of `config`/`module_factory` must be given.
|
|
72
|
+
|
|
68
73
|
Args:
|
|
69
74
|
config: Name of config file.
|
|
75
|
+
module_factory: Async factory that builds the Module once the event loop is already
|
|
76
|
+
running, instead of parsing a config file synchronously in __init__ -- lets the
|
|
77
|
+
factory `await` things (e.g. a login dialog's submit signal) before the module
|
|
78
|
+
(and its comm connection) exists at all. Mutually exclusive with `config`.
|
|
79
|
+
loop_module_class: Module class to pick `new_event_loop()` from when `module_factory`
|
|
80
|
+
is given (the caller already knows which module class it's about to build, e.g.
|
|
81
|
+
`GUI` in pyobs-gui's case). Required when `module_factory` is given, ignored
|
|
82
|
+
otherwise.
|
|
70
83
|
log_file: Name of log file, if any.
|
|
71
84
|
log_level: Logging level.
|
|
72
85
|
syslog: Send log to systemd journal, tagged with SYSLOG_IDENTIFIER=pyobs
|
|
73
86
|
and PYOBS_MODULE=<module name>. Requires logging-journald.
|
|
74
87
|
influx_log: Log to influx DB.
|
|
75
88
|
"""
|
|
89
|
+
if (config is None) == (module_factory is None):
|
|
90
|
+
raise ValueError("Exactly one of 'config' or 'module_factory' must be given.")
|
|
91
|
+
if module_factory is not None and loop_module_class is None:
|
|
92
|
+
raise ValueError("loop_module_class is required when module_factory is given.")
|
|
76
93
|
|
|
77
94
|
# get config name without path and extension
|
|
78
95
|
self._config = config
|
|
79
|
-
config_base =
|
|
96
|
+
config_base = (
|
|
97
|
+
os.path.splitext(os.path.basename(config))[0]
|
|
98
|
+
if config is not None
|
|
99
|
+
else loop_module_class.__name__.lower() # type: ignore[union-attr]
|
|
100
|
+
)
|
|
80
101
|
|
|
81
102
|
# filter that injects %(pyobs_module)s into every LogRecord from the context var
|
|
82
103
|
module_name_filter = ModuleNameFilter()
|
|
@@ -156,72 +177,100 @@ class Application:
|
|
|
156
177
|
|
|
157
178
|
log = logging.getLogger(__name__)
|
|
158
179
|
|
|
159
|
-
# set (maybe temporary) module name
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
#
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
180
|
+
# set (maybe temporary) module name -- filename without leading underscores for the
|
|
181
|
+
# config path, or a placeholder derived from loop_module_class for the factory path
|
|
182
|
+
# (there's no real name yet until the factory resolves the actual module/comm identity)
|
|
183
|
+
module_name.set(Path(self._config).stem.lstrip("_") if self._config is not None else config_base)
|
|
184
|
+
|
|
185
|
+
self._module: Module | None = None
|
|
186
|
+
self._module_factory = module_factory
|
|
187
|
+
|
|
188
|
+
if config is not None:
|
|
189
|
+
# load config
|
|
190
|
+
log.info("Loading configuration from %s...", config)
|
|
191
|
+
with StringIO(pre_process_yaml(config)) as f:
|
|
192
|
+
cfg: dict[str, Any] = yaml.safe_load(f)
|
|
193
|
+
|
|
194
|
+
# get module class
|
|
195
|
+
class_name = cfg["class"]
|
|
196
|
+
klass = get_class_from_string(class_name)
|
|
197
|
+
|
|
198
|
+
# create event loop — if top-level class doesn't override new_event_loop,
|
|
199
|
+
# check child modules for one that does (e.g. pyobs_gui.GUI in a MultiModule)
|
|
200
|
+
loop_class = klass
|
|
201
|
+
if klass.new_event_loop is Module.new_event_loop:
|
|
202
|
+
for mod_cfg in cfg.get("modules", {}).values():
|
|
203
|
+
if isinstance(mod_cfg, dict) and "class" in mod_cfg:
|
|
204
|
+
child_klass = get_class_from_string(mod_cfg["class"])
|
|
205
|
+
if child_klass.new_event_loop is not Module.new_event_loop:
|
|
206
|
+
loop_class = child_klass
|
|
207
|
+
break
|
|
208
|
+
self._loop = loop_class.new_event_loop()
|
|
209
|
+
asyncio.set_event_loop(self._loop)
|
|
210
|
+
|
|
211
|
+
# create module and open it
|
|
212
|
+
config_stem = Path(config).stem.lstrip("_")
|
|
213
|
+
if "comm" not in cfg and not issubclass(klass, MultiModule):
|
|
214
|
+
# no comm configured -- module would otherwise fall back to a DummyComm named
|
|
215
|
+
# with the fixed placeholder "module", indistinguishable from every other
|
|
216
|
+
# comm-less module in PYOBS_MODULE log tagging (see
|
|
217
|
+
# specs/steering/finding-module-logs-under-pyobsd.md) and guaranteed to trip the
|
|
218
|
+
# stem-mismatch check below. Give it the config file's own stem instead.
|
|
219
|
+
cfg = {**cfg, "comm": {"class": f"{DummyComm.__module__}.{DummyComm.__name__}", "name": config_stem}}
|
|
220
|
+
log.info("Creating module from class %s...", klass.__name__)
|
|
221
|
+
self._module = get_object(cfg, Module)
|
|
222
|
+
|
|
223
|
+
# a config file whose stem doesn't match its own module's name silently splits
|
|
224
|
+
# PYOBS_MODULE log tagging in two: logging that falls through both execute()
|
|
225
|
+
# (module.py) and BackgroundTask (background_task.py) stays on the filename set
|
|
226
|
+
# above, while logging covered by either of those uses the module's real
|
|
227
|
+
# Comm-derived name -- refuse to start rather than let that drift run undetected.
|
|
228
|
+
# MultiModule is exempt: its own .name is always the fixed placeholder "multi"
|
|
229
|
+
# (module.py), never meant to match a filename -- each child module is already
|
|
230
|
+
# correctly distinguished via execute()/BackgroundTask.
|
|
231
|
+
if not isinstance(self._module, MultiModule):
|
|
232
|
+
if self._module.name != config_stem:
|
|
233
|
+
log.warning(
|
|
234
|
+
"Config file stem (%s) does not match module's own name "
|
|
235
|
+
"(%s). Rename the config file or fix the module's "
|
|
236
|
+
"comm configuration so they match.",
|
|
237
|
+
config_stem,
|
|
238
|
+
self._module.name,
|
|
239
|
+
)
|
|
240
|
+
else:
|
|
241
|
+
# module_factory path: pick the event loop from the class the caller already knows
|
|
242
|
+
# it's about to build -- the module itself gets built later, inside the running
|
|
243
|
+
# loop (see _main()), since only there can the factory await anything.
|
|
244
|
+
assert loop_module_class is not None # validated above
|
|
245
|
+
self._loop = loop_module_class.new_event_loop()
|
|
246
|
+
asyncio.set_event_loop(self._loop)
|
|
213
247
|
|
|
214
248
|
def run(self) -> None:
|
|
215
249
|
"""Run app."""
|
|
216
250
|
|
|
251
|
+
# run main task forever -- created before the signal handlers are registered below, so
|
|
252
|
+
# a signal arriving the instant it's registered can never find self._main_task unset
|
|
253
|
+
self._main_task = self._loop.create_task(self._main())
|
|
254
|
+
|
|
217
255
|
# signals
|
|
218
256
|
for sig in (signal.SIGTERM, signal.SIGINT):
|
|
219
257
|
self._loop.add_signal_handler(sig, self._signal_handler, sig)
|
|
220
258
|
|
|
221
|
-
# run main task forever
|
|
222
|
-
main = self._loop.create_task(self._main())
|
|
223
259
|
self._loop.run_forever()
|
|
224
|
-
|
|
260
|
+
try:
|
|
261
|
+
self._loop.run_until_complete(self._main_task)
|
|
262
|
+
except asyncio.CancelledError:
|
|
263
|
+
# _signal_handler() cancelled _main_task directly -- only reachable while
|
|
264
|
+
# module_factory hadn't resolved yet (e.g. a login dialog still open), since
|
|
265
|
+
# self._module.quit() is what normally unblocks run_forever()/main otherwise.
|
|
266
|
+
pass
|
|
267
|
+
except RuntimeError:
|
|
268
|
+
# Qt-backed loops (qasync, used by pyobs-gui) can report the underlying Qt event
|
|
269
|
+
# loop as stopped before _main_task is done -- e.g. when the GUI's native window
|
|
270
|
+
# close triggers Qt's own quit independently of self._module.quit(). _main_task
|
|
271
|
+
# keeps running as a plain asyncio task regardless; the cancel/gather below still
|
|
272
|
+
# drains it, so this is a benign race in loop bookkeeping, not a failed shutdown.
|
|
273
|
+
log.warning("Event loop reported as stopped before shutdown finished; continuing cleanup.")
|
|
225
274
|
|
|
226
275
|
# main finished, cancel all tasks
|
|
227
276
|
tasks = asyncio.all_tasks(self._loop)
|
|
@@ -229,7 +278,11 @@ class Application:
|
|
|
229
278
|
log.debug("Task %s still running, cancelling it...", t)
|
|
230
279
|
t.cancel()
|
|
231
280
|
group = asyncio.gather(*tasks, return_exceptions=True)
|
|
232
|
-
|
|
281
|
+
try:
|
|
282
|
+
self._loop.run_until_complete(group)
|
|
283
|
+
except RuntimeError:
|
|
284
|
+
# same benign qasync race as above, now on the cancellation gather itself.
|
|
285
|
+
log.warning("Event loop reported as stopped before task cancellation finished.")
|
|
233
286
|
|
|
234
287
|
# finished
|
|
235
288
|
log.info("Closing loop...")
|
|
@@ -238,7 +291,14 @@ class Application:
|
|
|
238
291
|
def _signal_handler(self, sig: int) -> None:
|
|
239
292
|
"""React to signals and quit the module."""
|
|
240
293
|
|
|
241
|
-
self._module
|
|
294
|
+
if self._module is not None:
|
|
295
|
+
self._module.quit()
|
|
296
|
+
else:
|
|
297
|
+
# module_factory hasn't resolved yet (e.g. a login dialog still open) -- nothing to
|
|
298
|
+
# quit, so cancel the pending factory wait directly instead. Module.quit() would
|
|
299
|
+
# otherwise have called loop.stop() itself (module.py); mirror that here too.
|
|
300
|
+
self._main_task.cancel()
|
|
301
|
+
self._loop.stop()
|
|
242
302
|
|
|
243
303
|
# reset signal handlers
|
|
244
304
|
log.info("Got signal: %s, shutting down.", sig)
|
|
@@ -251,6 +311,15 @@ class Application:
|
|
|
251
311
|
|
|
252
312
|
# everything in a try/except/finally, so that we can shut down gracefully
|
|
253
313
|
try:
|
|
314
|
+
# resolve the module from the factory, if we're in that mode and haven't yet --
|
|
315
|
+
# runs inside the running loop, so the factory can await anything it needs to
|
|
316
|
+
# (e.g. a login dialog's submit signal) before the module/comm connection exists
|
|
317
|
+
if self._module is None:
|
|
318
|
+
assert self._module_factory is not None # validated in __init__
|
|
319
|
+
log.info("Waiting for module factory to resolve...")
|
|
320
|
+
self._module = await self._module_factory()
|
|
321
|
+
log.info("Module factory resolved.")
|
|
322
|
+
|
|
254
323
|
# open module
|
|
255
324
|
log.info("Opening module...")
|
|
256
325
|
await self._module.startup()
|
|
@@ -48,6 +48,26 @@ def _retry_delay(attempt: int, cap: float = 30.0, base: float = 1.0) -> float:
|
|
|
48
48
|
return random.uniform(0, min(cap, base * (2**attempt)))
|
|
49
49
|
|
|
50
50
|
|
|
51
|
+
# anchored at both ends -- re.match alone doesn't anchor the end, so e.g. "user@domain/res/extra"
|
|
52
|
+
# would otherwise still "match" as a valid prefix
|
|
53
|
+
_JID_RE = re.compile(r"([\w_\-\.]+)@([\w_\-\.]+)/([\w_\-\.]+)$")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def is_valid_jid(jid: str, resource: str = "pyobs") -> bool:
|
|
57
|
+
"""Whether jid is a valid user@domain or user@domain/resource JID -- exactly what
|
|
58
|
+
XmppComm.__init__ requires, so callers taking raw user input (e.g. a login window) can
|
|
59
|
+
validate it up front instead of finding out via a raised, less specific exception.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
jid: JID to check, with or without a resource part.
|
|
63
|
+
resource: Resource to assume if jid doesn't already include one -- must match whatever
|
|
64
|
+
XmppComm itself would be constructed with, since a resource-less jid is only valid
|
|
65
|
+
if *some* resource ends up attached to it.
|
|
66
|
+
"""
|
|
67
|
+
candidate = jid if "/" in jid else f"{jid}/{resource}"
|
|
68
|
+
return bool(_JID_RE.match(candidate))
|
|
69
|
+
|
|
70
|
+
|
|
51
71
|
class EventStanza(ElementBase):
|
|
52
72
|
name = "event"
|
|
53
73
|
namespace = "pyobs:event"
|
|
@@ -180,10 +200,10 @@ class XmppComm(Comm):
|
|
|
180
200
|
jid += "/" + resource
|
|
181
201
|
|
|
182
202
|
# get user/domain/resource and write it back to config
|
|
183
|
-
m =
|
|
203
|
+
m = _JID_RE.match(jid)
|
|
184
204
|
if not m:
|
|
185
|
-
log.error("Invalid JID format.")
|
|
186
|
-
raise ValueError()
|
|
205
|
+
log.error("Invalid JID format: %r (expected user@domain or user@domain/resource).", jid)
|
|
206
|
+
raise ValueError(f"Invalid JID format: {jid!r} (expected user@domain or user@domain/resource).")
|
|
187
207
|
self._user = m.group(1)
|
|
188
208
|
self._domain = m.group(2)
|
|
189
209
|
self._resource = m.group(3)
|
|
@@ -1161,4 +1181,4 @@ class XmppComm(Comm):
|
|
|
1161
1181
|
pass # already gone server-side
|
|
1162
1182
|
|
|
1163
1183
|
|
|
1164
|
-
__all__ = ["XmppComm"]
|
|
1184
|
+
__all__ = ["XmppComm", "is_valid_jid"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "pyobs-core"
|
|
3
|
-
version = "2.0.0.
|
|
3
|
+
version = "2.0.0.dev49"
|
|
4
4
|
description = "robotic telescope software"
|
|
5
5
|
authors = [{ name = "Tim-Oliver Husser", email = "thusser@uni-goettingen.de" }]
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -27,7 +27,7 @@ dependencies = [
|
|
|
27
27
|
"influxdb-client>=1.49.0",
|
|
28
28
|
"pydantic>=2.12.5",
|
|
29
29
|
"astropydantic>=0.0.5",
|
|
30
|
-
"pillow>=
|
|
30
|
+
"pillow>=12.3.0",
|
|
31
31
|
"tenacity>=9.1.4",
|
|
32
32
|
"psutil>=7.2.2",
|
|
33
33
|
"logging-journald>=0.6.11",
|
|
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.dev48 → pyobs_core-2.0.0.dev49}/pyobs/comm/xmpp/xep_0009_timeout/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/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.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/_daobackgroundremover.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/annotation/__init__.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/annotation/_pillow.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/annotation/circle.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/annotation/crosshair.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/annotation/text.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/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.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/astrometry/astrometry.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/astrometry/dotnet.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/calibration/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/calibration/calibration.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/detection/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/detection/daophot.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/detection/pysep.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/detection/simpledisk.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/exptime/__init__.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/exptime/exptime.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/image/addfitsheaders.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/image/grayscale.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/image/httpserver.py
RENAMED
|
File without changes
|
{pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/image/normalize.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyobs_core-2.0.0.dev48 → pyobs_core-2.0.0.dev49}/pyobs/images/processors/image/saveimage.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|