pyobs-core 2.0.0.dev17__tar.gz → 2.0.0.dev19__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.dev17 → pyobs_core-2.0.0.dev19}/PKG-INFO +1 -1
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/cli/pyobsd.py +34 -5
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/comm/comm.py +12 -20
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/comm/local/localcomm.py +4 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/serializer.py +8 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/xmppcomm.py +7 -3
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IModule.py +10 -1
- pyobs_core-2.0.0.dev19/pyobs/interfaces/IPointingBody.py +29 -0
- pyobs_core-2.0.0.dev19/pyobs/interfaces/IPointingHeliocentricPolar.py +41 -0
- pyobs_core-2.0.0.dev17/pyobs/interfaces/IPointingHGS.py → pyobs_core-2.0.0.dev19/pyobs/interfaces/IPointingHeliographicStonyhurst.py +7 -6
- pyobs_core-2.0.0.dev19/pyobs/interfaces/IPointingOrbitalElements.py +47 -0
- pyobs_core-2.0.0.dev19/pyobs/interfaces/ITrackingMode.py +54 -0
- pyobs_core-2.0.0.dev19/pyobs/interfaces/ITrackingRate.py +54 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/__init__.py +22 -4
- pyobs_core-2.0.0.dev19/pyobs/interfaces/interface.py +77 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/mixins/fitsheader.py +16 -12
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/camera/basevideo.py +3 -9
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/module.py +44 -8
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/_baseguiding.py +2 -1
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/acquisition.py +2 -1
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/robotic/mastermind.py +1 -1
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/robotic/scheduler.py +3 -3
- pyobs_core-2.0.0.dev19/pyobs/modules/telescope/__init__.py +13 -0
- pyobs_core-2.0.0.dev17/pyobs/modules/telescope/dummytelescope.py → pyobs_core-2.0.0.dev19/pyobs/modules/telescope/_dummytelescopebase.py +63 -35
- pyobs_core-2.0.0.dev19/pyobs/modules/telescope/basetelescope.py +815 -0
- pyobs_core-2.0.0.dev19/pyobs/modules/telescope/dummyaltaztelescope.py +46 -0
- pyobs_core-2.0.0.dev19/pyobs/modules/telescope/dummyradectelescope.py +55 -0
- pyobs_core-2.0.0.dev19/pyobs/modules/telescope/dummysolartelescope.py +149 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/utils/__init__.py +1 -2
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/object.py +15 -17
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/skyflats/flatfielder.py +1 -1
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/enums.py +6 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/grids/filters.py +6 -6
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/serialization.py +0 -3
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyproject.toml +1 -1
- pyobs_core-2.0.0.dev17/pyobs/interfaces/interface.py +0 -36
- pyobs_core-2.0.0.dev17/pyobs/modules/telescope/__init__.py +0 -11
- pyobs_core-2.0.0.dev17/pyobs/modules/telescope/basetelescope.py +0 -353
- pyobs_core-2.0.0.dev17/pyobs/modules/utils/autonomouswarning.py +0 -153
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/.gitignore +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/LICENSE +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/application.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/background_task.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/cli/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/cli/_cli.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/cli/pyobs.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/cli/pyobsw.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/comm/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/comm/commlogging.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/comm/dummy/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/comm/dummy/dummycomm.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/comm/local/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/comm/local/localnetwork.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/comm/proxy.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/rpc.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/xep_0009/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/xep_0009/binding.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/xep_0009/rpc.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/xep_0009_timeout/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/xep_0009_timeout/rpc.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/xep_0009_timeout/stanza/RPC.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/xep_0009_timeout/stanza/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/xmppclient.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/events/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/events/badweather.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/events/event.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/events/exposurestatuschanged.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/events/filterchanged.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/events/focusfound.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/events/goodweather.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/events/log.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/events/modechanged.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/events/moduleclosed.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/events/moduleopened.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/events/motionstatuschanged.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/events/move.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/events/newimage.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/events/newspectrum.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/events/offsets.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/events/roofclosing.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/events/roofopened.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/events/taskfailed.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/events/taskfinished.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/events/taskstarted.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/events/testevent.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/image.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/meta/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/meta/altazoffsets.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/meta/exptime.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/meta/genericoffset.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/meta/onskydistance.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/meta/pixeloffsets.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/meta/radecoffsets.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/meta/skyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processor.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/_daobackgroundremover.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/annotation/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/annotation/_pillow.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/annotation/circle.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/annotation/crosshair.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/annotation/text.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/astrometry/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/astrometry/_dotnet_request.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/astrometry/_dotnet_request_builder.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/astrometry/_dotnet_request_logger.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/astrometry/_dotnet_response_saver.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/astrometry/astrometry.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/astrometry/dotnet.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/calibration/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/calibration/_calibration_cache.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/calibration/_ccddata_calibrator.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/calibration/calibration.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/detection/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/detection/_pysep_stats_calculator.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/detection/_source_catalog.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/detection/daophot.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/detection/pysep.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/detection/simpledisk.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/detection/sourcedetection.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/exptime/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/exptime/exptime.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/exptime/star.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/image/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/image/addfitsheaders.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/image/download.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/image/flip.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/image/grayscale.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/image/httpserver.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/image/normalize.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/image/save.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/image/saveimage.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/image/smooth.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/image/softbin.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/misc/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/misc/addmask.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/misc/catalogcircularmask.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/misc/circularmask.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/misc/createfilename.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/misc/imagesourcefilter.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/misc/removebackground.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/modules/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/modules/getfitsheaders.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/offsets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/offsets/astrometry.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/offsets/brighteststar.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/offsets/brighteststar_guiding.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/offsets/dummyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/offsets/dummyskyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/offsets/fitsheader.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/offsets/offsets.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/offsets/pixeloffsets.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/offsets/projected.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/offsets/spilled_light.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/photometry/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/photometry/_photometry_calculator.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/photometry/_photutil_aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/photometry/_sep_aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/photometry/aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/photometry/photometry.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/photometry/photutil.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/photometry/pysep.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/wcs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/wcs/solarhelioprojective.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IAbortable.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IAcquisition.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IAutoFocus.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IAutoGuiding.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IAutonomous.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IBinning.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/ICalibrate.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/ICamera.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IConfig.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/ICooling.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IData.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IDome.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IExposure.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IExposureTime.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IFilters.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IFitsHeaderAfter.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IFitsHeaderBefore.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IFlatField.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IFocusModel.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IFocuser.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IGain.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IImageFormat.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IImageType.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IMode.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IMotion.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IMultiFiber.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IOffsetsAltAz.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IOffsetsRaDec.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IPointingAltAz.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IPointingHelioprojective.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IPointingRaDec.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IPointingSeries.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IReady.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IRoof.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IRotation.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IRunnable.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IRunning.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IScriptRunner.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/ISpectrograph.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IStartStop.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IStructuredConfig.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/ISyncTarget.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/ITelescope.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/ITemperatures.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IVideo.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IWeather.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IWindow.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/mixins/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/mixins/camerasettings.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/mixins/fitsnamespace.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/mixins/follow.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/mixins/motionstatus.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/mixins/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/mixins/waitformotion.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/mixins/weatheraware.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/camera/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/camera/adaptive.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/camera/basecamera.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/camera/basespectrograph.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/camera/dummycamera.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/camera/dummyspectrograph.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/camera/dummyvideo.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/camera/pipelinecamera.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/flatfield/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/flatfield/flatfield.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/flatfield/pointing.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/flatfield/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/focus/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/focus/dummyautofocus.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/focus/focusmodel.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/focus/focusseries.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/image/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/image/imagewatcher.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/image/imagewriter.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/image/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/image/seeing.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/_base.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/autoguiding.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/dummyacquisition.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/dummyguiding.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/guidingstatistics/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/guidingstatistics/guidingstatistics.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/guidingstatistics/pixeloffset.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/guidingstatistics/skyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/guidingstatistics/uptime.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/scienceframeguiding.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/robotic/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/robotic/pointing.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/robotic/scriptrunner.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/roof/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/roof/basedome.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/roof/baseroof.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/roof/dummyroof.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/test/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/test/standalone.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/utils/dummymode.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/utils/fluentlogger.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/utils/httpfilecache.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/utils/kiosk.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/utils/matrix.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/utils/stellarium.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/utils/telegram.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/utils/trigger.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/weather/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/weather/mockweather.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/weather/weather.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/weather/weather_api.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/modules/weather/weather_state.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/py.typed +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/observation.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/astroplanscheduler.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/constraints/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/constraints/airmassconstraint.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/constraints/constraint.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/constraints/moonilluminationconstraint.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/constraints/moonseparationconstraint.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/constraints/solarelevationconstraint.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/constraints/timeconstraint.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/dataprovider.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/merits/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/merits/aftertime.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/merits/beforetime.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/merits/constant.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/merits/follow.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/merits/interval.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/merits/merit.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/merits/pernight.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/merits/random.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/merits/timewindow.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/merits/transit.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/observationarchiveevolution.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/ondemandscheduler.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/targets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/targets/dynamictarget.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/targets/heliocentricpolartarget.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/targets/helioprojectivetarget.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/targets/picker/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/targets/picker/csvpicker.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/targets/picker/picker.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/targets/siderealtarget.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/targets/target.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/taskscheduler.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/calibration/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/calibration/darkbias.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/calibration/pointing.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/calibration/skyflats.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/control/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/control/cases.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/control/conditional.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/control/parallel.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/control/selector.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/control/sequential.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/imaging/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/imaging/autofocus.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/imaging/imaging.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/imaging/transitimaging.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/script.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/utils/callmodule.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/utils/debugtrigger.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/utils/log.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/backend/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/backend/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/backend/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/filesystem/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/filesystem/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/filesystem/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/_portal.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/_schedulereader.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/_schedulewriter.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/configdb.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/mockobservationarchive.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/scripts/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/scripts/autofocus.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/scripts/default.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/scripts/script.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/task.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/taskrunner.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/memory/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/memory/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/memory/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/task.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/taskrunner.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/archive/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/archive/archive.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/archive/local_archive.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/archive/pyobs_archive.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/exptime/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/exptime/exptime.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/exptime/stellarexptime.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/skyflats/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/skyflats/exptimeeval.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/skyflats/pointing/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/skyflats/pointing/base.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/skyflats/pointing/static.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/skyflats/priorities/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/skyflats/priorities/archive.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/skyflats/priorities/base.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/skyflats/priorities/const.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/skyflats/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/average.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/cache.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/config.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/config_schema.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/coordinates.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/curvefit.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/exceptions.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/fits.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/focusseries/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/focusseries/base.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/focusseries/photometry.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/focusseries/projection.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/grids/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/grids/grid.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/grids/gridnode.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/grids/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/gui/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/gui/camera/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/gui/camera/binningwidget.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/gui/camera/datadisplaywidget.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/gui/camera/exposewidget.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/gui/camera/exposuretimewidget.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/gui/camera/imageformatwidget.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/gui/camera/listpickerdialog.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/gui/camera/windowingwidget.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/http.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/influxdb.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/logger.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/logging/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/logging/context.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/logging/resolvableerror.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/modulegui.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/offsets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/offsets/applyaltazoffsets.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/offsets/applyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/offsets/applyradecoffsets.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/parallel.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/pipeline/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/pipeline/night.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/pipeline/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/publisher/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/publisher/csv.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/publisher/http.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/publisher/log.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/publisher/multi.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/publisher/publisher.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/shellcommand.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/threads/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/threads/lockwithabort.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/time.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/utils/units.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/version.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/vfs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/vfs/archivefile.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/vfs/bufferedfile.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/vfs/file.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/vfs/filelists/__init__.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/vfs/filelists/filelist.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/vfs/filelists/testing.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/vfs/httpfile.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/vfs/localfile.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/vfs/memfile.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/vfs/sftpfile.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/vfs/smbfile.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/vfs/sshfile.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/vfs/tempfile.py +0 -0
- {pyobs_core-2.0.0.dev17 → pyobs_core-2.0.0.dev19}/pyobs/vfs/vfs.py +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import argparse
|
|
3
4
|
import glob
|
|
4
5
|
import json
|
|
5
6
|
import logging
|
|
@@ -49,9 +50,9 @@ class PyobsDaemonCLI(CLI):
|
|
|
49
50
|
)
|
|
50
51
|
self._parser.add_argument(
|
|
51
52
|
"--syslog",
|
|
52
|
-
action=
|
|
53
|
-
help="send module logs to systemd journal",
|
|
54
|
-
default=self._config.get("syslog",
|
|
53
|
+
action=argparse.BooleanOptionalAction,
|
|
54
|
+
help="send module logs to systemd journal (use --no-syslog to disable)",
|
|
55
|
+
default=self._config.get("syslog", True),
|
|
55
56
|
)
|
|
56
57
|
self._parser.add_argument("--chuid", type=str, default=self._config.get("chuid", "pyobs:pyobs"))
|
|
57
58
|
self._parser.add_argument("-v", "--verbose", action="store_true")
|
|
@@ -63,6 +64,9 @@ class PyobsDaemonCLI(CLI):
|
|
|
63
64
|
sp.add_parser("restart", help="restart modules").add_argument("modules", type=str, nargs="*")
|
|
64
65
|
sp.add_parser("status", help="status of modules").add_argument("--json", action="store_true")
|
|
65
66
|
sp.add_parser("list", help="list of modules")
|
|
67
|
+
sp.add_parser("logs", help="show/follow module logs via journalctl").add_argument(
|
|
68
|
+
"args", nargs=argparse.REMAINDER, help="[module] [journalctl arguments...]"
|
|
69
|
+
)
|
|
66
70
|
|
|
67
71
|
def run(self) -> None:
|
|
68
72
|
# init daemon
|
|
@@ -87,7 +91,9 @@ class PyobsDaemonCLI(CLI):
|
|
|
87
91
|
case "status":
|
|
88
92
|
daemon.status(print_json=self._config["json"])
|
|
89
93
|
case "list":
|
|
90
|
-
daemon.
|
|
94
|
+
daemon.list_modules()
|
|
95
|
+
case "logs":
|
|
96
|
+
daemon.logs(self._config["args"])
|
|
91
97
|
|
|
92
98
|
|
|
93
99
|
class PyobsDaemon:
|
|
@@ -289,9 +295,24 @@ class PyobsDaemon:
|
|
|
289
295
|
else:
|
|
290
296
|
print(f"{module:<30} {'stopped':<8}")
|
|
291
297
|
|
|
292
|
-
def
|
|
298
|
+
def list_modules(self) -> None:
|
|
293
299
|
print("\n".join(self._list_configs()))
|
|
294
300
|
|
|
301
|
+
def logs(self, args: list[str]) -> None:
|
|
302
|
+
"""Show/follow module logs by exec'ing into journalctl."""
|
|
303
|
+
match_args = ["SYSLOG_IDENTIFIER=pyobs"]
|
|
304
|
+
remainder = list(args)
|
|
305
|
+
# "--" may have been auto-inserted by main() to work around argparse.REMAINDER
|
|
306
|
+
# refusing to swallow a leading flag (e.g. "pyobsd logs -f") — drop it here.
|
|
307
|
+
if remainder and remainder[0] == "--":
|
|
308
|
+
remainder.pop(0)
|
|
309
|
+
if remainder and remainder[0] in self._list_configs():
|
|
310
|
+
match_args.append(f"PYOBS_MODULE={remainder.pop(0)}")
|
|
311
|
+
cmd = ["journalctl", *match_args, *remainder]
|
|
312
|
+
if self._verbose:
|
|
313
|
+
print(f"[DEBUG] Executing: {' '.join(cmd)}")
|
|
314
|
+
os.execvp("journalctl", cmd)
|
|
315
|
+
|
|
295
316
|
# ── process management ────────────────────────────────────────────────────
|
|
296
317
|
|
|
297
318
|
def _start_service(self, module: str) -> None:
|
|
@@ -388,6 +409,14 @@ class PyobsDaemon:
|
|
|
388
409
|
|
|
389
410
|
|
|
390
411
|
def main() -> None:
|
|
412
|
+
# argparse.REMAINDER can't swallow a leading flag (e.g. "pyobsd logs -f")
|
|
413
|
+
# unless a "--" already precedes it — insert one automatically so users
|
|
414
|
+
# don't need to type it themselves.
|
|
415
|
+
if "logs" in sys.argv:
|
|
416
|
+
idx = sys.argv.index("logs") + 1
|
|
417
|
+
if idx < len(sys.argv) and sys.argv[idx].startswith("-") and sys.argv[idx] != "--":
|
|
418
|
+
sys.argv.insert(idx, "--")
|
|
419
|
+
|
|
391
420
|
cli = PyobsDaemonCLI()
|
|
392
421
|
cli()
|
|
393
422
|
|
|
@@ -7,9 +7,9 @@ import logging
|
|
|
7
7
|
from collections.abc import Callable, Coroutine
|
|
8
8
|
from typing import TYPE_CHECKING, Any, overload
|
|
9
9
|
|
|
10
|
-
import pyobs.interfaces
|
|
11
10
|
from pyobs.events import Event, LogEvent, ModuleClosedEvent
|
|
12
11
|
from pyobs.interfaces import Interface
|
|
12
|
+
from pyobs.interfaces.interface import get_registered_interface
|
|
13
13
|
from pyobs.utils.enums import ModuleState
|
|
14
14
|
|
|
15
15
|
from .commlogging import CommLoggingHandler
|
|
@@ -337,28 +337,13 @@ class Comm:
|
|
|
337
337
|
list of interface classes.
|
|
338
338
|
"""
|
|
339
339
|
|
|
340
|
-
# get interface classes
|
|
341
|
-
inspection = inspect.getmembers(pyobs.interfaces, predicate=inspect.isclass)
|
|
342
|
-
|
|
343
340
|
# loop interfaces
|
|
344
341
|
interface_classes = []
|
|
345
342
|
for interface_name in interfaces:
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
if interface_name == cls_name and issubclass(cls, Interface):
|
|
351
|
-
# found it!
|
|
352
|
-
found = True
|
|
353
|
-
|
|
354
|
-
# then add it to the list of all interfaces
|
|
355
|
-
interface_classes.append(cls)
|
|
356
|
-
|
|
357
|
-
# there can only be one...
|
|
358
|
-
break
|
|
359
|
-
|
|
360
|
-
# not found?
|
|
361
|
-
if not found:
|
|
343
|
+
cls = get_registered_interface(interface_name)
|
|
344
|
+
if cls is not None:
|
|
345
|
+
interface_classes.append(cls)
|
|
346
|
+
else:
|
|
362
347
|
log.error('Could not find interface "%s" for client.', interface_name)
|
|
363
348
|
return interface_classes
|
|
364
349
|
|
|
@@ -541,6 +526,13 @@ class Comm:
|
|
|
541
526
|
def _get_own_state(self, interface: type[Interface]) -> Any:
|
|
542
527
|
return None
|
|
543
528
|
|
|
529
|
+
def get_own_capabilities(self, interface: type[Interface]) -> Any:
|
|
530
|
+
"""Return the capabilities published by this module for the given interface, or None."""
|
|
531
|
+
return self._get_own_capabilities(interface)
|
|
532
|
+
|
|
533
|
+
def _get_own_capabilities(self, interface: type[Interface]) -> Any:
|
|
534
|
+
return None
|
|
535
|
+
|
|
544
536
|
async def subscribe_state(
|
|
545
537
|
self,
|
|
546
538
|
module: str,
|
|
@@ -117,6 +117,10 @@ class LocalComm(Comm):
|
|
|
117
117
|
"""Store capabilities locally."""
|
|
118
118
|
self._capabilities[interface] = capabilities
|
|
119
119
|
|
|
120
|
+
def _get_own_capabilities(self, interface: type[Interface]) -> Any:
|
|
121
|
+
"""Return this client's own published capabilities."""
|
|
122
|
+
return self._capabilities.get(interface)
|
|
123
|
+
|
|
120
124
|
async def _get_capabilities(self, module: str, interface: type[Interface]) -> Any | None:
|
|
121
125
|
"""Fetch capabilities from a remote module."""
|
|
122
126
|
if interface.capabilities is None:
|
|
@@ -32,6 +32,7 @@ import types as _builtin_types
|
|
|
32
32
|
from enum import StrEnum
|
|
33
33
|
from typing import Annotated, Any, Union, get_args, get_origin, get_type_hints
|
|
34
34
|
|
|
35
|
+
import numpy as np
|
|
35
36
|
from slixmpp.xmlstream import ET
|
|
36
37
|
|
|
37
38
|
from ...interfaces.interface import Interface as _Interface
|
|
@@ -65,6 +66,13 @@ def value_to_xml(value: Any, type_hint: Any) -> ET.Element:
|
|
|
65
66
|
if get_origin(type_hint) is Annotated:
|
|
66
67
|
type_hint = get_args(type_hint)[0]
|
|
67
68
|
|
|
69
|
+
# Normalize numpy scalars (np.float64, np.int64, np.bool_, ...) to native
|
|
70
|
+
# Python types. np.float64 subclasses float but repr()s as "np.float64(x)"
|
|
71
|
+
# since numpy 2.0, which corrupts <double> text; numpy integer types don't
|
|
72
|
+
# subclass int at all and would otherwise fall through to <string>.
|
|
73
|
+
if isinstance(value, np.generic):
|
|
74
|
+
value = value.item()
|
|
75
|
+
|
|
68
76
|
# None / void
|
|
69
77
|
if value is None:
|
|
70
78
|
elem = ET.Element("nil")
|
|
@@ -18,11 +18,11 @@ from slixmpp.xmlstream import ET
|
|
|
18
18
|
from slixmpp.xmlstream.handler import Callback
|
|
19
19
|
from slixmpp.xmlstream.matcher import MatchXMLMask
|
|
20
20
|
|
|
21
|
-
import pyobs.interfaces
|
|
22
21
|
from pyobs.comm import Comm
|
|
23
22
|
from pyobs.events import Event, LogEvent, ModuleClosedEvent, ModuleOpenedEvent
|
|
24
23
|
from pyobs.events.event import EventFactory
|
|
25
24
|
from pyobs.interfaces import Interface
|
|
25
|
+
from pyobs.interfaces.interface import get_registered_interface
|
|
26
26
|
from pyobs.utils import exceptions as exc
|
|
27
27
|
from pyobs.utils.enums import ModuleState
|
|
28
28
|
|
|
@@ -406,8 +406,8 @@ class XmppComm(Comm):
|
|
|
406
406
|
interface_names = []
|
|
407
407
|
for feature in features:
|
|
408
408
|
name, _, version = feature[len(prefix) :].rpartition(":")
|
|
409
|
-
local_cls =
|
|
410
|
-
if local_cls is not None and
|
|
409
|
+
local_cls = get_registered_interface(name)
|
|
410
|
+
if local_cls is not None and str(local_cls.version) == version:
|
|
411
411
|
interface_names.append(name)
|
|
412
412
|
|
|
413
413
|
# IModule not in list?
|
|
@@ -896,6 +896,10 @@ class XmppComm(Comm):
|
|
|
896
896
|
self._capabilities[interface] = capabilities
|
|
897
897
|
log.info("Published capabilities for %s", interface.__name__)
|
|
898
898
|
|
|
899
|
+
def _get_own_capabilities(self, interface: type[Interface]) -> Any:
|
|
900
|
+
"""Return this client's own published capabilities."""
|
|
901
|
+
return self._capabilities.get(interface)
|
|
902
|
+
|
|
899
903
|
async def _get_capabilities(self, module: str, interface: type[Interface]) -> Any | None:
|
|
900
904
|
"""Fetch and deserialize capabilities for a remote module's interface."""
|
|
901
905
|
if interface.capabilities is None:
|
|
@@ -7,10 +7,19 @@ from typing import Any
|
|
|
7
7
|
from .interface import Interface
|
|
8
8
|
|
|
9
9
|
|
|
10
|
+
@dataclass
|
|
11
|
+
class ModuleLocation:
|
|
12
|
+
longitude: float = 0.0
|
|
13
|
+
latitude: float = 0.0
|
|
14
|
+
elevation: float = 0.0
|
|
15
|
+
timezone: str = "utc"
|
|
16
|
+
|
|
17
|
+
|
|
10
18
|
@dataclass
|
|
11
19
|
class ModuleCapabilities:
|
|
12
20
|
label: str = ""
|
|
13
21
|
version: str = ""
|
|
22
|
+
location: ModuleLocation | None = None
|
|
14
23
|
|
|
15
24
|
|
|
16
25
|
class IModule(Interface, metaclass=ABCMeta):
|
|
@@ -31,4 +40,4 @@ class IModule(Interface, metaclass=ABCMeta):
|
|
|
31
40
|
...
|
|
32
41
|
|
|
33
42
|
|
|
34
|
-
__all__ = ["IModule", "ModuleCapabilities"]
|
|
43
|
+
__all__ = ["IModule", "ModuleCapabilities", "ModuleLocation"]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from abc import ABCMeta, abstractmethod
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from .interface import Interface
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class IPointingBody(Interface, metaclass=ABCMeta):
|
|
10
|
+
"""Points at and tracks a named solar-system body."""
|
|
11
|
+
|
|
12
|
+
__module__ = "pyobs.interfaces"
|
|
13
|
+
|
|
14
|
+
@abstractmethod
|
|
15
|
+
async def track_body(self, body: str, **kwargs: Any) -> None:
|
|
16
|
+
"""Starts tracking a named solar-system body.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
body: Name resolvable to an ephemeris (e.g. 'moon', 'mars', 'jupiter', or an
|
|
20
|
+
asteroid/comet designation known to JPL Horizons).
|
|
21
|
+
|
|
22
|
+
Raises:
|
|
23
|
+
MoveError: If telescope could not be moved.
|
|
24
|
+
ValueError: If body name is not resolvable.
|
|
25
|
+
"""
|
|
26
|
+
...
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
__all__ = ["IPointingBody"]
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from abc import ABCMeta, abstractmethod
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from typing import Annotated, Any
|
|
6
|
+
|
|
7
|
+
from ..utils.enums import Unit
|
|
8
|
+
from ..utils.time import Time
|
|
9
|
+
from .interface import Interface
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class HeliocentricPolarState:
|
|
14
|
+
mu: float
|
|
15
|
+
psi: Annotated[float, Unit.DEGREES]
|
|
16
|
+
time: Time = field(default_factory=Time.now)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class IPointingHeliocentricPolar(Interface, metaclass=ABCMeta):
|
|
20
|
+
"""The module can move to Heliocentric Polar (Mu/Psi) coordinates, usually combined with
|
|
21
|
+
:class:`~pyobs.interfaces.ITelescope`."""
|
|
22
|
+
|
|
23
|
+
__module__ = "pyobs.interfaces"
|
|
24
|
+
|
|
25
|
+
state = HeliocentricPolarState
|
|
26
|
+
|
|
27
|
+
@abstractmethod
|
|
28
|
+
async def move_heliocentric_polar(self, mu: float, psi: Annotated[float, Unit.DEGREES], **kwargs: Any) -> None:
|
|
29
|
+
"""Moves on given coordinates.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
mu: Cosine of the angular distance from Sun centre, dimensionless (0..1).
|
|
33
|
+
psi: Position angle around the solar disk, in degrees.
|
|
34
|
+
|
|
35
|
+
Raises:
|
|
36
|
+
MoveError: If device could not be moved.
|
|
37
|
+
"""
|
|
38
|
+
...
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
__all__ = ["IPointingHeliocentricPolar", "HeliocentricPolarState"]
|
|
@@ -10,21 +10,22 @@ from .interface import Interface
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
@dataclass
|
|
13
|
-
class
|
|
13
|
+
class HeliographicStonyhurstState:
|
|
14
14
|
lon: Annotated[float, Unit.DEGREES]
|
|
15
15
|
lat: Annotated[float, Unit.DEGREES]
|
|
16
16
|
time: Time = field(default_factory=Time.now)
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
class
|
|
20
|
-
"""The module can move to
|
|
19
|
+
class IPointingHeliographicStonyhurst(Interface, metaclass=ABCMeta):
|
|
20
|
+
"""The module can move to Heliographic Stonyhurst (lon/lat) coordinates, a frame fixed to the Sun's
|
|
21
|
+
rotating surface, usually combined with :class:`~pyobs.interfaces.ITelescope`."""
|
|
21
22
|
|
|
22
23
|
__module__ = "pyobs.interfaces"
|
|
23
24
|
|
|
24
|
-
state =
|
|
25
|
+
state = HeliographicStonyhurstState
|
|
25
26
|
|
|
26
27
|
@abstractmethod
|
|
27
|
-
async def
|
|
28
|
+
async def move_heliographic_stonyhurst(
|
|
28
29
|
self, lon: Annotated[float, Unit.DEGREES], lat: Annotated[float, Unit.DEGREES], **kwargs: Any
|
|
29
30
|
) -> None:
|
|
30
31
|
"""Moves on given coordinates.
|
|
@@ -39,4 +40,4 @@ class IPointingHGS(Interface, metaclass=ABCMeta):
|
|
|
39
40
|
...
|
|
40
41
|
|
|
41
42
|
|
|
42
|
-
__all__ = ["
|
|
43
|
+
__all__ = ["IPointingHeliographicStonyhurst", "HeliographicStonyhurstState"]
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from abc import ABCMeta, abstractmethod
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Annotated, Any
|
|
6
|
+
|
|
7
|
+
from ..utils.enums import Unit
|
|
8
|
+
from ..utils.time import Time
|
|
9
|
+
from .interface import Interface
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class OrbitalElements:
|
|
14
|
+
epoch: Time
|
|
15
|
+
semi_major_axis: Annotated[float, Unit.AU]
|
|
16
|
+
eccentricity: float
|
|
17
|
+
inclination: Annotated[float, Unit.DEGREES]
|
|
18
|
+
longitude_ascending_node: Annotated[float, Unit.DEGREES]
|
|
19
|
+
argument_of_periapsis: Annotated[float, Unit.DEGREES]
|
|
20
|
+
mean_anomaly: Annotated[float, Unit.DEGREES] | None = None
|
|
21
|
+
"""Mean anomaly at epoch, in degrees. Required for elliptical orbits (eccentricity < 1)."""
|
|
22
|
+
perihelion_time: Time | None = None
|
|
23
|
+
"""Time of perihelion passage. Required for near-parabolic/cometary orbits
|
|
24
|
+
(eccentricity close to or at 1), where mean anomaly is not well-defined."""
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class IPointingOrbitalElements(Interface, metaclass=ABCMeta):
|
|
28
|
+
"""Points at and tracks a body defined by orbital elements (asteroid, comet, NEO)."""
|
|
29
|
+
|
|
30
|
+
__module__ = "pyobs.interfaces"
|
|
31
|
+
|
|
32
|
+
@abstractmethod
|
|
33
|
+
async def track_orbital_elements(self, elements: OrbitalElements, **kwargs: Any) -> None:
|
|
34
|
+
"""Starts tracking a body defined by orbital elements.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
elements: Orbital elements of the body to track.
|
|
38
|
+
|
|
39
|
+
Raises:
|
|
40
|
+
MoveError: If telescope could not be moved.
|
|
41
|
+
ValueError: If elements are incomplete or inconsistent (neither mean_anomaly
|
|
42
|
+
nor perihelion_time given).
|
|
43
|
+
"""
|
|
44
|
+
...
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
__all__ = ["IPointingOrbitalElements", "OrbitalElements"]
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from abc import ABCMeta, abstractmethod
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from enum import StrEnum
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from ..utils.time import Time
|
|
9
|
+
from .interface import Interface
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TrackingMode(StrEnum):
|
|
13
|
+
"""Discrete, hardware-native tracking rate."""
|
|
14
|
+
|
|
15
|
+
SIDEREAL = "sidereal"
|
|
16
|
+
SOLAR = "solar"
|
|
17
|
+
LUNAR = "lunar"
|
|
18
|
+
OFF = "off"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class TrackingModeState:
|
|
23
|
+
mode: TrackingMode
|
|
24
|
+
time: Time = field(default_factory=Time.now)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class TrackingModeCapabilities:
|
|
29
|
+
modes: list[TrackingMode]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ITrackingMode(Interface, metaclass=ABCMeta):
|
|
33
|
+
"""The module supports switching between discrete, hardware-native tracking rates."""
|
|
34
|
+
|
|
35
|
+
__module__ = "pyobs.interfaces"
|
|
36
|
+
|
|
37
|
+
state = TrackingModeState
|
|
38
|
+
capabilities = TrackingModeCapabilities
|
|
39
|
+
|
|
40
|
+
@abstractmethod
|
|
41
|
+
async def set_tracking_mode(self, mode: TrackingMode, **kwargs: Any) -> None:
|
|
42
|
+
"""Switches to the given tracking mode.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
mode: Tracking mode to switch to.
|
|
46
|
+
|
|
47
|
+
Raises:
|
|
48
|
+
MoveError: If mode could not be set.
|
|
49
|
+
ValueError: If mode is not in this module's capabilities.
|
|
50
|
+
"""
|
|
51
|
+
...
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
__all__ = ["ITrackingMode", "TrackingMode", "TrackingModeState", "TrackingModeCapabilities"]
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from abc import ABCMeta, abstractmethod
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from typing import Annotated, Any
|
|
6
|
+
|
|
7
|
+
from ..utils.enums import Unit
|
|
8
|
+
from ..utils.time import Time
|
|
9
|
+
from .interface import Interface
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class TrackingRateState:
|
|
14
|
+
ra_rate: Annotated[float, Unit.ARCSEC_PER_SEC]
|
|
15
|
+
dec_rate: Annotated[float, Unit.ARCSEC_PER_SEC]
|
|
16
|
+
time: Time = field(default_factory=Time.now)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass
|
|
20
|
+
class TrackingRateCapabilities:
|
|
21
|
+
min_update_interval: Annotated[float, Unit.SECONDS]
|
|
22
|
+
"""Minimum time between successive set_tracking_rate calls this hardware/protocol accepts,
|
|
23
|
+
independent of whether the value actually changed. Populated per-driver from whatever its
|
|
24
|
+
protocol allows; 0 if the hardware has no such floor."""
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ITrackingRate(Interface, metaclass=ABCMeta):
|
|
28
|
+
"""The module accepts an arbitrary non-sidereal tracking rate as an absolute RA/Dec offset."""
|
|
29
|
+
|
|
30
|
+
__module__ = "pyobs.interfaces"
|
|
31
|
+
|
|
32
|
+
state = TrackingRateState
|
|
33
|
+
capabilities = TrackingRateCapabilities
|
|
34
|
+
|
|
35
|
+
@abstractmethod
|
|
36
|
+
async def set_tracking_rate(
|
|
37
|
+
self,
|
|
38
|
+
ra_rate: Annotated[float, Unit.ARCSEC_PER_SEC],
|
|
39
|
+
dec_rate: Annotated[float, Unit.ARCSEC_PER_SEC],
|
|
40
|
+
**kwargs: Any,
|
|
41
|
+
) -> None:
|
|
42
|
+
"""Sets an absolute tracking rate on the sky, in arcsec/sec.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
ra_rate: Rate in RA, arcsec/sec on the sky.
|
|
46
|
+
dec_rate: Rate in Dec, arcsec/sec on the sky.
|
|
47
|
+
|
|
48
|
+
Raises:
|
|
49
|
+
MoveError: If rate could not be set.
|
|
50
|
+
"""
|
|
51
|
+
...
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
__all__ = ["ITrackingRate", "TrackingRateState", "TrackingRateCapabilities"]
|
|
@@ -36,15 +36,18 @@ from .IGain import GainState, IGain
|
|
|
36
36
|
from .IImageFormat import IImageFormat, ImageFormatCapabilities, ImageFormatState
|
|
37
37
|
from .IImageType import IImageType, ImageTypeState
|
|
38
38
|
from .IMode import IMode, ModeCapabilities, ModeState
|
|
39
|
-
from .IModule import IModule, ModuleCapabilities
|
|
39
|
+
from .IModule import IModule, ModuleCapabilities, ModuleLocation
|
|
40
40
|
from .IMotion import DeviceMotionStatus, IMotion, MotionState
|
|
41
41
|
from .IMultiFiber import IMultiFiber, MultiFiberCapabilities, MultiFiberState
|
|
42
42
|
from .interface import Interface
|
|
43
43
|
from .IOffsetsAltAz import AltAzOffsetState, IOffsetsAltAz
|
|
44
44
|
from .IOffsetsRaDec import IOffsetsRaDec, RaDecOffsetState
|
|
45
45
|
from .IPointingAltAz import AltAzState, IPointingAltAz
|
|
46
|
+
from .IPointingBody import IPointingBody
|
|
47
|
+
from .IPointingHeliocentricPolar import HeliocentricPolarState, IPointingHeliocentricPolar
|
|
48
|
+
from .IPointingHeliographicStonyhurst import HeliographicStonyhurstState, IPointingHeliographicStonyhurst
|
|
46
49
|
from .IPointingHelioprojective import HelioprojectiveState, IPointingHelioprojective
|
|
47
|
-
from .
|
|
50
|
+
from .IPointingOrbitalElements import IPointingOrbitalElements, OrbitalElements
|
|
48
51
|
from .IPointingRaDec import IPointingRaDec, RaDecState
|
|
49
52
|
from .IPointingSeries import IPointingSeries
|
|
50
53
|
from .IReady import IReady, ReadyState
|
|
@@ -59,6 +62,8 @@ from .IStructuredConfig import ConfigAppliedState, ConfigFieldSchema, ConfigSche
|
|
|
59
62
|
from .ISyncTarget import ISyncTarget
|
|
60
63
|
from .ITelescope import ITelescope
|
|
61
64
|
from .ITemperatures import ITemperatures, SensorReading, TemperaturesState
|
|
65
|
+
from .ITrackingMode import ITrackingMode, TrackingMode, TrackingModeCapabilities, TrackingModeState
|
|
66
|
+
from .ITrackingRate import ITrackingRate, TrackingRateCapabilities, TrackingRateState
|
|
62
67
|
from .IVideo import IVideo, VideoCapabilities
|
|
63
68
|
from .IWeather import IWeather, WeatherSensorReading, WeatherState
|
|
64
69
|
from .IWindow import IWindow, WindowCapabilities, WindowState
|
|
@@ -118,6 +123,7 @@ __all__ = [
|
|
|
118
123
|
"ModeState",
|
|
119
124
|
"IModule",
|
|
120
125
|
"ModuleCapabilities",
|
|
126
|
+
"ModuleLocation",
|
|
121
127
|
"IMotion",
|
|
122
128
|
"DeviceMotionStatus",
|
|
123
129
|
"MotionState",
|
|
@@ -126,10 +132,15 @@ __all__ = [
|
|
|
126
132
|
"MultiFiberState",
|
|
127
133
|
"IPointingAltAz",
|
|
128
134
|
"AltAzState",
|
|
135
|
+
"IPointingBody",
|
|
136
|
+
"IPointingHeliocentricPolar",
|
|
137
|
+
"HeliocentricPolarState",
|
|
138
|
+
"IPointingHeliographicStonyhurst",
|
|
139
|
+
"HeliographicStonyhurstState",
|
|
129
140
|
"IPointingHelioprojective",
|
|
130
141
|
"HelioprojectiveState",
|
|
131
|
-
"
|
|
132
|
-
"
|
|
142
|
+
"IPointingOrbitalElements",
|
|
143
|
+
"OrbitalElements",
|
|
133
144
|
"IPointingRaDec",
|
|
134
145
|
"RaDecState",
|
|
135
146
|
"IPointingSeries",
|
|
@@ -152,6 +163,13 @@ __all__ = [
|
|
|
152
163
|
"ITemperatures",
|
|
153
164
|
"SensorReading",
|
|
154
165
|
"TemperaturesState",
|
|
166
|
+
"ITrackingMode",
|
|
167
|
+
"TrackingMode",
|
|
168
|
+
"TrackingModeState",
|
|
169
|
+
"TrackingModeCapabilities",
|
|
170
|
+
"ITrackingRate",
|
|
171
|
+
"TrackingRateState",
|
|
172
|
+
"TrackingRateCapabilities",
|
|
155
173
|
"IOffsetsAltAz",
|
|
156
174
|
"AltAzOffsetState",
|
|
157
175
|
"IOffsetsRaDec",
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from abc import ABCMeta
|
|
2
|
+
from typing import Any, ClassVar
|
|
3
|
+
|
|
4
|
+
_REGISTRY: dict[str, "type[Interface]"] = {}
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Interface(metaclass=ABCMeta):
|
|
8
|
+
"""Base class for all interfaces in pyobs."""
|
|
9
|
+
|
|
10
|
+
version: int = 1
|
|
11
|
+
state: ClassVar[type | None] = None
|
|
12
|
+
capabilities: ClassVar[type | None] = None
|
|
13
|
+
|
|
14
|
+
__module__ = "pyobs.interfaces"
|
|
15
|
+
|
|
16
|
+
def __init_subclass__(cls, **kwargs: Any) -> None:
|
|
17
|
+
super().__init_subclass__(**kwargs)
|
|
18
|
+
|
|
19
|
+
# only genuine interface definitions get registered. Concrete module
|
|
20
|
+
# classes (e.g. `class BaseCamera(Module, ICamera, IExposureTime,
|
|
21
|
+
# IImageType)`) also transitively subclass Interface, but always mix
|
|
22
|
+
# in at least one base that isn't itself an Interface subclass
|
|
23
|
+
# (Module, a FITS-header mixin, ...). A base only counts as "pure"
|
|
24
|
+
# if it's Interface itself or is already registered -- issubclass(
|
|
25
|
+
# base, Interface) alone isn't enough, since e.g. BaseCamera
|
|
26
|
+
# transitively satisfies that (via ICamera) despite mixing in
|
|
27
|
+
# Module, which would let DummyCamera(BaseCamera, ...) register
|
|
28
|
+
# too. Checking registry membership instead propagates purity down
|
|
29
|
+
# the whole chain, since BaseCamera itself never gets registered.
|
|
30
|
+
def _is_pure(base: type) -> bool:
|
|
31
|
+
return base is Interface or _REGISTRY.get(base.__name__) is base
|
|
32
|
+
|
|
33
|
+
if not all(_is_pure(base) for base in cls.__bases__):
|
|
34
|
+
return
|
|
35
|
+
|
|
36
|
+
existing = _REGISTRY.get(cls.__name__)
|
|
37
|
+
if existing is not None and existing is not cls:
|
|
38
|
+
raise TypeError(
|
|
39
|
+
f"Interface name '{cls.__name__}' is already registered by "
|
|
40
|
+
f"{existing.__module__}.{existing.__qualname__}; "
|
|
41
|
+
f"choose a distinct name for {cls.__module__}.{cls.__qualname__}."
|
|
42
|
+
)
|
|
43
|
+
_REGISTRY[cls.__name__] = cls
|
|
44
|
+
|
|
45
|
+
def get_state(self, interface: "type[Interface]") -> Any | None:
|
|
46
|
+
"""Return the last received state for the given interface, or None."""
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
def get_capabilities(self, interface: "type[Interface]") -> Any | None:
|
|
50
|
+
"""Return the capabilities for the given interface, or None."""
|
|
51
|
+
return None
|
|
52
|
+
|
|
53
|
+
async def wait_for_state(self, interface: "type[Interface]", timeout: float = 10.0) -> Any | None:
|
|
54
|
+
"""Return state immediately if available, otherwise wait for the first update."""
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
@classmethod
|
|
58
|
+
def has_own_state(cls) -> bool:
|
|
59
|
+
"""True if this interface defines its own state, as opposed to merely inheriting
|
|
60
|
+
one from a component interface it combines (e.g. ICamera inheriting IExposure's
|
|
61
|
+
state). Modules publish state under the interface that actually defines it, so
|
|
62
|
+
composite interfaces would otherwise be (wrongly) treated as publishing state too.
|
|
63
|
+
"""
|
|
64
|
+
return "state" in cls.__dict__
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def get_registered_interface(name: str) -> "type[Interface] | None":
|
|
68
|
+
"""Look up a registered interface class by name, or None if unknown."""
|
|
69
|
+
return _REGISTRY.get(name)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def registered_interfaces() -> "dict[str, type[Interface]]":
|
|
73
|
+
"""All currently-registered interface classes, keyed by name."""
|
|
74
|
+
return dict(_REGISTRY)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
__all__ = ["Interface", "get_registered_interface", "registered_interfaces"]
|