pyobs-core 2.0.0.dev41__tar.gz → 2.0.0.dev43__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.
Files changed (445) hide show
  1. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/PKG-INFO +1 -1
  2. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/application.py +1 -1
  3. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/comm/comm.py +11 -4
  4. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/comm/local/localcomm.py +14 -1
  5. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/comm/proxy.py +31 -8
  6. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/comm/xmpp/xmppcomm.py +8 -0
  7. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/interface.py +4 -2
  8. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/mixins/weatheraware.py +5 -2
  9. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/camera/basecamera.py +5 -2
  10. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/camera/dummycamera.py +6 -0
  11. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/flatfield/flatfield.py +0 -8
  12. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/flatfield/scheduler.py +0 -8
  13. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/focus/focusseries.py +0 -4
  14. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/module.py +11 -0
  15. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/pointing/_base.py +0 -12
  16. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/pointing/acquisition.py +0 -6
  17. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/weather/weather.py +4 -0
  18. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyproject.toml +1 -1
  19. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/.gitignore +0 -0
  20. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/LICENSE +0 -0
  21. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/__init__.py +0 -0
  22. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/background_task.py +0 -0
  23. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/cli/__init__.py +0 -0
  24. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/cli/_cli.py +0 -0
  25. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/cli/pyobs.py +0 -0
  26. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/cli/pyobsd.py +0 -0
  27. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/cli/pyobsw.py +0 -0
  28. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/comm/__init__.py +0 -0
  29. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/comm/commlogging.py +0 -0
  30. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/comm/dummy/__init__.py +0 -0
  31. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/comm/dummy/dummycomm.py +0 -0
  32. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/comm/local/__init__.py +0 -0
  33. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/comm/local/localnetwork.py +0 -0
  34. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/comm/xmpp/__init__.py +0 -0
  35. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/comm/xmpp/rpc.py +0 -0
  36. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/comm/xmpp/serializer.py +0 -0
  37. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/comm/xmpp/xep_0009/__init__.py +0 -0
  38. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/comm/xmpp/xep_0009/binding.py +0 -0
  39. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/comm/xmpp/xep_0009/rpc.py +0 -0
  40. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/comm/xmpp/xep_0009_timeout/__init__.py +0 -0
  41. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/comm/xmpp/xep_0009_timeout/rpc.py +0 -0
  42. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/comm/xmpp/xep_0009_timeout/stanza/RPC.py +0 -0
  43. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/comm/xmpp/xep_0009_timeout/stanza/__init__.py +0 -0
  44. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/comm/xmpp/xmppclient.py +0 -0
  45. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/events/__init__.py +0 -0
  46. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/events/badweather.py +0 -0
  47. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/events/event.py +0 -0
  48. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/events/exposurestatuschanged.py +0 -0
  49. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/events/filterchanged.py +0 -0
  50. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/events/focusfound.py +0 -0
  51. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/events/goodweather.py +0 -0
  52. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/events/log.py +0 -0
  53. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/events/modechanged.py +0 -0
  54. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/events/moduleclosed.py +0 -0
  55. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/events/moduleopened.py +0 -0
  56. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/events/motionstatuschanged.py +0 -0
  57. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/events/move.py +0 -0
  58. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/events/newimage.py +0 -0
  59. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/events/newspectrum.py +0 -0
  60. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/events/offsets.py +0 -0
  61. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/events/roofclosing.py +0 -0
  62. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/events/roofopened.py +0 -0
  63. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/events/taskfailed.py +0 -0
  64. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/events/taskfinished.py +0 -0
  65. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/events/taskstarted.py +0 -0
  66. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/events/testevent.py +0 -0
  67. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/__init__.py +0 -0
  68. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/image.py +0 -0
  69. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/meta/__init__.py +0 -0
  70. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/meta/altazoffsets.py +0 -0
  71. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/meta/exptime.py +0 -0
  72. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/meta/genericoffset.py +0 -0
  73. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/meta/onskydistance.py +0 -0
  74. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/meta/pixeloffsets.py +0 -0
  75. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/meta/radecoffsets.py +0 -0
  76. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/meta/skyoffsets.py +0 -0
  77. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processor.py +0 -0
  78. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/__init__.py +0 -0
  79. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/_daobackgroundremover.py +0 -0
  80. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/annotation/__init__.py +0 -0
  81. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/annotation/_pillow.py +0 -0
  82. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/annotation/circle.py +0 -0
  83. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/annotation/crosshair.py +0 -0
  84. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/annotation/text.py +0 -0
  85. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/astrometry/__init__.py +0 -0
  86. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/astrometry/_dotnet_request.py +0 -0
  87. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/astrometry/_dotnet_request_builder.py +0 -0
  88. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/astrometry/_dotnet_request_logger.py +0 -0
  89. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/astrometry/_dotnet_response_saver.py +0 -0
  90. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/astrometry/astrometry.py +0 -0
  91. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/astrometry/dotnet.py +0 -0
  92. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/calibration/__init__.py +0 -0
  93. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/calibration/_calibration_cache.py +0 -0
  94. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/calibration/_ccddata_calibrator.py +0 -0
  95. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/calibration/calibration.py +0 -0
  96. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/detection/__init__.py +0 -0
  97. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/detection/_pysep_stats_calculator.py +0 -0
  98. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/detection/_source_catalog.py +0 -0
  99. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/detection/daophot.py +0 -0
  100. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/detection/pysep.py +0 -0
  101. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/detection/simpledisk.py +0 -0
  102. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/detection/sourcedetection.py +0 -0
  103. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/exptime/__init__.py +0 -0
  104. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/exptime/exptime.py +0 -0
  105. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/exptime/star.py +0 -0
  106. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/image/__init__.py +0 -0
  107. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/image/addfitsheaders.py +0 -0
  108. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/image/download.py +0 -0
  109. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/image/flip.py +0 -0
  110. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/image/grayscale.py +0 -0
  111. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/image/httpserver.py +0 -0
  112. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/image/normalize.py +0 -0
  113. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/image/save.py +0 -0
  114. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/image/saveimage.py +0 -0
  115. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/image/smooth.py +0 -0
  116. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/image/softbin.py +0 -0
  117. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/misc/__init__.py +0 -0
  118. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/misc/addmask.py +0 -0
  119. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/misc/catalogcircularmask.py +0 -0
  120. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/misc/circularmask.py +0 -0
  121. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/misc/createfilename.py +0 -0
  122. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/misc/imagesourcefilter.py +0 -0
  123. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/misc/removebackground.py +0 -0
  124. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/modules/__init__.py +0 -0
  125. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/modules/getfitsheaders.py +0 -0
  126. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/offsets/__init__.py +0 -0
  127. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/offsets/astrometry.py +0 -0
  128. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/offsets/brighteststar.py +0 -0
  129. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/offsets/brighteststar_guiding.py +0 -0
  130. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/offsets/dummyoffsets.py +0 -0
  131. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/offsets/dummyskyoffsets.py +0 -0
  132. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/offsets/fitsheader.py +0 -0
  133. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/offsets/offsets.py +0 -0
  134. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/offsets/pixeloffsets.py +0 -0
  135. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/offsets/projected.py +0 -0
  136. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/offsets/spilled_light.py +0 -0
  137. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/photometry/__init__.py +0 -0
  138. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/photometry/_photometry_calculator.py +0 -0
  139. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/photometry/_photutil_aperture_photometry.py +0 -0
  140. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/photometry/_sep_aperture_photometry.py +0 -0
  141. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/photometry/aperture_photometry.py +0 -0
  142. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/photometry/photometry.py +0 -0
  143. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/photometry/photutil.py +0 -0
  144. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/photometry/pysep.py +0 -0
  145. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/wcs/__init__.py +0 -0
  146. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/images/processors/wcs/solarhelioprojective.py +0 -0
  147. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IAbortable.py +0 -0
  148. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IAcquisition.py +0 -0
  149. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IAutoFocus.py +0 -0
  150. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IAutoGuiding.py +0 -0
  151. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IAutonomous.py +0 -0
  152. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IBinning.py +0 -0
  153. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/ICalibrate.py +0 -0
  154. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/ICamera.py +0 -0
  155. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IConfig.py +0 -0
  156. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/ICooling.py +0 -0
  157. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IData.py +0 -0
  158. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IDataSequence.py +0 -0
  159. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IDome.py +0 -0
  160. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IExposure.py +0 -0
  161. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IExposureTime.py +0 -0
  162. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IFilters.py +0 -0
  163. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IFitsHeaderAfter.py +0 -0
  164. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IFitsHeaderBefore.py +0 -0
  165. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IFlatField.py +0 -0
  166. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IFocusModel.py +0 -0
  167. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IFocuser.py +0 -0
  168. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IGain.py +0 -0
  169. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IImageFormat.py +0 -0
  170. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IImageType.py +0 -0
  171. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IMode.py +0 -0
  172. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IModule.py +0 -0
  173. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IMotion.py +0 -0
  174. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IMultiFiber.py +0 -0
  175. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IOffsetsAltAz.py +0 -0
  176. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IOffsetsRaDec.py +0 -0
  177. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IPointingAltAz.py +0 -0
  178. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IPointingBody.py +0 -0
  179. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IPointingHeliocentricPolar.py +0 -0
  180. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IPointingHeliographicStonyhurst.py +0 -0
  181. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IPointingHelioprojective.py +0 -0
  182. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IPointingOrbitalElements.py +0 -0
  183. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IPointingRaDec.py +0 -0
  184. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IPointingSeries.py +0 -0
  185. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IReady.py +0 -0
  186. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IRoof.py +0 -0
  187. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IRotation.py +0 -0
  188. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IRunnable.py +0 -0
  189. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IRunning.py +0 -0
  190. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IScriptRunner.py +0 -0
  191. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/ISpectrograph.py +0 -0
  192. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IStartStop.py +0 -0
  193. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IStructuredConfig.py +0 -0
  194. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/ISyncTarget.py +0 -0
  195. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/ITelescope.py +0 -0
  196. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/ITemperatures.py +0 -0
  197. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/ITrackingMode.py +0 -0
  198. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/ITrackingRate.py +0 -0
  199. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IVideo.py +0 -0
  200. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IWeather.py +0 -0
  201. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/IWindow.py +0 -0
  202. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/interfaces/__init__.py +0 -0
  203. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/mixins/__init__.py +0 -0
  204. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/mixins/camerasettings.py +0 -0
  205. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/mixins/fitsheader.py +0 -0
  206. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/mixins/fitsnamespace.py +0 -0
  207. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/mixins/follow.py +0 -0
  208. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/mixins/motionstatus.py +0 -0
  209. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/mixins/pipeline.py +0 -0
  210. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/mixins/waitformotion.py +0 -0
  211. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/__init__.py +0 -0
  212. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/camera/__init__.py +0 -0
  213. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/camera/adaptive.py +0 -0
  214. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/camera/basespectrograph.py +0 -0
  215. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/camera/basevideo.py +0 -0
  216. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/camera/dummyspectrograph.py +0 -0
  217. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/camera/dummyvideo.py +0 -0
  218. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/camera/pipelinecamera.py +0 -0
  219. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/flatfield/__init__.py +0 -0
  220. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/flatfield/pointing.py +0 -0
  221. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/focus/__init__.py +0 -0
  222. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/focus/dummyautofocus.py +0 -0
  223. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/focus/focusmodel.py +0 -0
  224. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/image/__init__.py +0 -0
  225. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/image/imagewatcher.py +0 -0
  226. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/image/imagewriter.py +0 -0
  227. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/image/pipeline.py +0 -0
  228. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/image/seeing.py +0 -0
  229. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/pointing/__init__.py +0 -0
  230. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/pointing/_baseguiding.py +0 -0
  231. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/pointing/autoguiding.py +0 -0
  232. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/pointing/dummyacquisition.py +0 -0
  233. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/pointing/dummyguiding.py +0 -0
  234. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/pointing/guidingstatistics/__init__.py +0 -0
  235. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/pointing/guidingstatistics/guidingstatistics.py +0 -0
  236. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/pointing/guidingstatistics/pixeloffset.py +0 -0
  237. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/pointing/guidingstatistics/skyoffsets.py +0 -0
  238. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/pointing/guidingstatistics/uptime.py +0 -0
  239. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/pointing/scienceframeguiding.py +0 -0
  240. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/robotic/__init__.py +0 -0
  241. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/robotic/mastermind.py +0 -0
  242. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/robotic/pointing.py +0 -0
  243. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/robotic/scheduler.py +0 -0
  244. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/robotic/scriptrunner.py +0 -0
  245. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/roof/__init__.py +0 -0
  246. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/roof/basedome.py +0 -0
  247. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/roof/baseroof.py +0 -0
  248. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/roof/dummyroof.py +0 -0
  249. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/telescope/__init__.py +0 -0
  250. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/telescope/_dummytelescopebase.py +0 -0
  251. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/telescope/basetelescope.py +0 -0
  252. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/telescope/dummyaltaztelescope.py +0 -0
  253. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/telescope/dummyradectelescope.py +0 -0
  254. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/telescope/dummysolartelescope.py +0 -0
  255. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/test/__init__.py +0 -0
  256. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/test/standalone.py +0 -0
  257. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/utils/__init__.py +0 -0
  258. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/utils/dummymode.py +0 -0
  259. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/utils/fluentlogger.py +0 -0
  260. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/utils/httpfilecache.py +0 -0
  261. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/utils/kiosk.py +0 -0
  262. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/utils/matrix.py +0 -0
  263. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/utils/stellarium.py +0 -0
  264. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/utils/telegram.py +0 -0
  265. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/utils/trigger.py +0 -0
  266. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/weather/__init__.py +0 -0
  267. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/weather/mockweather.py +0 -0
  268. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/weather/weather_api.py +0 -0
  269. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/modules/weather/weather_state.py +0 -0
  270. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/object.py +0 -0
  271. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/py.typed +0 -0
  272. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/__init__.py +0 -0
  273. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/observation.py +0 -0
  274. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/__init__.py +0 -0
  275. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/astroplanscheduler.py +0 -0
  276. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/constraints/__init__.py +0 -0
  277. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/constraints/airmassconstraint.py +0 -0
  278. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/constraints/constraint.py +0 -0
  279. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/constraints/moonilluminationconstraint.py +0 -0
  280. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/constraints/moonseparationconstraint.py +0 -0
  281. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/constraints/solarelevationconstraint.py +0 -0
  282. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/constraints/timeconstraint.py +0 -0
  283. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/dataprovider.py +0 -0
  284. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/merits/__init__.py +0 -0
  285. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/merits/aftertime.py +0 -0
  286. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/merits/beforetime.py +0 -0
  287. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/merits/constant.py +0 -0
  288. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/merits/follow.py +0 -0
  289. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/merits/interval.py +0 -0
  290. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/merits/merit.py +0 -0
  291. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/merits/pernight.py +0 -0
  292. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/merits/random.py +0 -0
  293. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/merits/timewindow.py +0 -0
  294. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/merits/transit.py +0 -0
  295. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/observationarchiveevolution.py +0 -0
  296. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/ondemandscheduler.py +0 -0
  297. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/targets/__init__.py +0 -0
  298. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/targets/dynamictarget.py +0 -0
  299. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/targets/heliocentricpolartarget.py +0 -0
  300. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/targets/helioprojectivetarget.py +0 -0
  301. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/targets/picker/__init__.py +0 -0
  302. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/targets/picker/csvpicker.py +0 -0
  303. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/targets/picker/picker.py +0 -0
  304. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/targets/siderealtarget.py +0 -0
  305. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/targets/target.py +0 -0
  306. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scheduler/taskscheduler.py +0 -0
  307. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scripts/__init__.py +0 -0
  308. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scripts/calibration/__init__.py +0 -0
  309. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scripts/calibration/darkbias.py +0 -0
  310. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scripts/calibration/pointing.py +0 -0
  311. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scripts/calibration/skyflats.py +0 -0
  312. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scripts/control/__init__.py +0 -0
  313. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scripts/control/cases.py +0 -0
  314. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scripts/control/conditional.py +0 -0
  315. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scripts/control/parallel.py +0 -0
  316. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scripts/control/selector.py +0 -0
  317. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scripts/control/sequential.py +0 -0
  318. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scripts/exceptions.py +0 -0
  319. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scripts/imaging/__init__.py +0 -0
  320. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scripts/imaging/autofocus.py +0 -0
  321. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scripts/imaging/imaging.py +0 -0
  322. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scripts/imaging/transitimaging.py +0 -0
  323. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scripts/script.py +0 -0
  324. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scripts/utils/__init__.py +0 -0
  325. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scripts/utils/callmodule.py +0 -0
  326. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scripts/utils/debugtrigger.py +0 -0
  327. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/scripts/utils/log.py +0 -0
  328. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/__init__.py +0 -0
  329. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/backend/__init__.py +0 -0
  330. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/backend/observationarchive.py +0 -0
  331. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/backend/taskarchive.py +0 -0
  332. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/filesystem/__init__.py +0 -0
  333. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/filesystem/observationarchive.py +0 -0
  334. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/filesystem/taskarchive.py +0 -0
  335. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/lco/__init__.py +0 -0
  336. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/lco/_portal.py +0 -0
  337. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/lco/_schedulereader.py +0 -0
  338. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/lco/_schedulewriter.py +0 -0
  339. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/lco/configdb.py +0 -0
  340. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/lco/mockobservationarchive.py +0 -0
  341. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/lco/observationarchive.py +0 -0
  342. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/lco/scripts/__init__.py +0 -0
  343. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/lco/scripts/autofocus.py +0 -0
  344. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/lco/scripts/default.py +0 -0
  345. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/lco/scripts/script.py +0 -0
  346. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/lco/task.py +0 -0
  347. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/lco/taskarchive.py +0 -0
  348. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/lco/taskrunner.py +0 -0
  349. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/memory/__init__.py +0 -0
  350. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/memory/observationarchive.py +0 -0
  351. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/memory/taskarchive.py +0 -0
  352. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/observationarchive.py +0 -0
  353. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/storage/taskarchive.py +0 -0
  354. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/task.py +0 -0
  355. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/taskrunner.py +0 -0
  356. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/utils/__init__.py +0 -0
  357. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/utils/archive/__init__.py +0 -0
  358. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/utils/archive/archive.py +0 -0
  359. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/utils/archive/local_archive.py +0 -0
  360. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/utils/archive/pyobs_archive.py +0 -0
  361. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/utils/exptime/__init__.py +0 -0
  362. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/utils/exptime/exptime.py +0 -0
  363. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/utils/exptime/stellarexptime.py +0 -0
  364. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/utils/skyflats/__init__.py +0 -0
  365. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/utils/skyflats/exptimeeval.py +0 -0
  366. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/utils/skyflats/flatfielder.py +0 -0
  367. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/utils/skyflats/pointing/__init__.py +0 -0
  368. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/utils/skyflats/pointing/base.py +0 -0
  369. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/utils/skyflats/pointing/static.py +0 -0
  370. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/utils/skyflats/priorities/__init__.py +0 -0
  371. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/utils/skyflats/priorities/archive.py +0 -0
  372. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/utils/skyflats/priorities/base.py +0 -0
  373. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/utils/skyflats/priorities/const.py +0 -0
  374. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/robotic/utils/skyflats/scheduler.py +0 -0
  375. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/__init__.py +0 -0
  376. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/average.py +0 -0
  377. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/cache.py +0 -0
  378. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/config.py +0 -0
  379. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/config_schema.py +0 -0
  380. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/coordinates.py +0 -0
  381. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/curvefit.py +0 -0
  382. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/enums.py +0 -0
  383. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/exceptions.py +0 -0
  384. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/fits.py +0 -0
  385. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/focusseries/__init__.py +0 -0
  386. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/focusseries/base.py +0 -0
  387. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/focusseries/photometry.py +0 -0
  388. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/focusseries/projection.py +0 -0
  389. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/grids/__init__.py +0 -0
  390. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/grids/filters.py +0 -0
  391. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/grids/grid.py +0 -0
  392. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/grids/gridnode.py +0 -0
  393. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/grids/pipeline.py +0 -0
  394. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/gui/__init__.py +0 -0
  395. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/gui/camera/__init__.py +0 -0
  396. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/gui/camera/binningwidget.py +0 -0
  397. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/gui/camera/datadisplaywidget.py +0 -0
  398. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/gui/camera/exposewidget.py +0 -0
  399. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/gui/camera/exposuretimewidget.py +0 -0
  400. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/gui/camera/imageformatwidget.py +0 -0
  401. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/gui/camera/listpickerdialog.py +0 -0
  402. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/gui/camera/windowingwidget.py +0 -0
  403. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/http.py +0 -0
  404. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/influxdb.py +0 -0
  405. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/logger.py +0 -0
  406. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/logging/__init__.py +0 -0
  407. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/logging/context.py +0 -0
  408. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/logging/resolvableerror.py +0 -0
  409. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/modulegui.py +0 -0
  410. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/offsets/__init__.py +0 -0
  411. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/offsets/applyaltazoffsets.py +0 -0
  412. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/offsets/applyoffsets.py +0 -0
  413. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/offsets/applyradecoffsets.py +0 -0
  414. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/parallel.py +0 -0
  415. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/pipeline/__init__.py +0 -0
  416. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/pipeline/night.py +0 -0
  417. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/pipeline/pipeline.py +0 -0
  418. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/publisher/__init__.py +0 -0
  419. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/publisher/csv.py +0 -0
  420. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/publisher/http.py +0 -0
  421. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/publisher/log.py +0 -0
  422. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/publisher/multi.py +0 -0
  423. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/publisher/publisher.py +0 -0
  424. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/serialization.py +0 -0
  425. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/shellcommand.py +0 -0
  426. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/threads/__init__.py +0 -0
  427. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/threads/lockwithabort.py +0 -0
  428. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/time.py +0 -0
  429. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/utils/units.py +0 -0
  430. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/version.py +0 -0
  431. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/vfs/__init__.py +0 -0
  432. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/vfs/archivefile.py +0 -0
  433. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/vfs/bufferedfile.py +0 -0
  434. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/vfs/file.py +0 -0
  435. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/vfs/filelists/__init__.py +0 -0
  436. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/vfs/filelists/filelist.py +0 -0
  437. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/vfs/filelists/testing.py +0 -0
  438. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/vfs/httpfile.py +0 -0
  439. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/vfs/localfile.py +0 -0
  440. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/vfs/memfile.py +0 -0
  441. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/vfs/sftpfile.py +0 -0
  442. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/vfs/smbfile.py +0 -0
  443. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/vfs/sshfile.py +0 -0
  444. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/pyobs/vfs/tempfile.py +0 -0
  445. {pyobs_core-2.0.0.dev41 → pyobs_core-2.0.0.dev43}/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.dev41
3
+ Version: 2.0.0.dev43
4
4
  Summary: robotic telescope software
5
5
  Author-email: Tim-Oliver Husser <thusser@uni-goettingen.de>
6
6
  License-Expression: MIT
@@ -193,7 +193,7 @@ class Application:
193
193
  # (module.py), never meant to match a filename -- each child module is already
194
194
  # correctly distinguished via execute()/BackgroundTask.
195
195
  if not isinstance(self._module, MultiModule):
196
- config_stem = Path(self._config).stem
196
+ config_stem = Path(self._config).stem.lstrip("_")
197
197
  if self._module.name != config_stem:
198
198
  log.warning(
199
199
  "Config file stem (%s) does not match module's own name "
@@ -41,6 +41,7 @@ class Comm:
41
41
  self._event_handlers: dict[type[Event], list[Callable[[Event, str], Coroutine[Any, Any, bool]]]] = {}
42
42
  self._registered_events: set[type[Event]] = set()
43
43
  self._closing = asyncio.Event()
44
+ self._published_state: set[type[Interface]] = set()
44
45
 
45
46
  @property
46
47
  def has_module(self) -> bool:
@@ -479,11 +480,17 @@ class Comm:
479
480
  interface: Interface type for the state.
480
481
  state: State object to publish.
481
482
  """
483
+ self._published_state.add(interface)
482
484
  await self._set_state(interface, state)
483
485
 
484
486
  async def _set_state(self, interface: type[Interface], state: Any) -> None:
485
487
  pass
486
488
 
489
+ def missing_published_state(self, interfaces: list[type[Interface]]) -> list[type[Interface]]:
490
+ """Return interfaces (from the given list) that declare state via has_own_state() but
491
+ haven't had set_state() called for them yet."""
492
+ return [i for i in interfaces if i.has_own_state() and i not in self._published_state]
493
+
487
494
  async def set_capabilities(self, interface: type[Interface], capabilities: Any) -> None:
488
495
  """Publish capabilities for this module.
489
496
 
@@ -535,10 +542,10 @@ class Comm:
535
542
  safe for peers to discover.
536
543
 
537
544
  Called by Module once it transitions to READY. Transports that announce a module to peers
538
- independently of RPC dispatch (e.g. XmppComm's XMPP presence, which drives other modules'
539
- peer-discovery reaction) hold that announcement back until this fires, so peers never read
540
- capabilities that are still mid-publish. Transports without such an announcement (e.g.
541
- LocalComm) don't need to override this.
545
+ independently of RPC dispatch (e.g. XmppComm's XMPP presence, or LocalComm's direct
546
+ ModuleOpenedEvent dispatch to already-connected peers) hold that announcement back until
547
+ this fires, so peers never read capabilities that are still mid-publish. Transports without
548
+ such an announcement don't need to override this.
542
549
  """
543
550
  await self._mark_ready()
544
551
 
@@ -5,7 +5,7 @@ from typing import Any
5
5
 
6
6
  from pyobs.comm import Comm
7
7
  from pyobs.comm.comm import PresenceCallback
8
- from pyobs.events import Event
8
+ from pyobs.events import Event, ModuleOpenedEvent
9
9
  from pyobs.interfaces import Interface
10
10
  from pyobs.utils.enums import ModuleState
11
11
 
@@ -26,6 +26,7 @@ class LocalComm(Comm):
26
26
  self._capabilities: dict[type[Interface], Any] = {} # interface -> Capabilities object
27
27
  self._presence: tuple[ModuleState, str] = (ModuleState.READY, "")
28
28
  self._presence_callbacks: dict[str, list[PresenceCallback]] = {}
29
+ self._ready = False
29
30
 
30
31
  @property
31
32
  def name(self) -> str:
@@ -158,3 +159,15 @@ class LocalComm(Comm):
158
159
  callback(*remote._presence)
159
160
  except KeyError:
160
161
  pass
162
+
163
+ async def _mark_ready(self) -> None:
164
+ """Announce this module to already-connected peers, mirroring XmppComm's presence-based
165
+ discovery (_got_online sending ModuleOpenedEvent) -- without this, a module that joins the
166
+ LocalNetwork after a peer has already started is invisible to that peer's ModuleOpenedEvent
167
+ handlers until the peer restarts (see #677). Guarded so a later re-READY doesn't re-announce."""
168
+ if self._ready:
169
+ return
170
+ self._ready = True
171
+ for client in self._network.get_clients():
172
+ if client is not self:
173
+ client._send_event_to_module(ModuleOpenedEvent(), self._name)
@@ -7,6 +7,7 @@ from collections.abc import Coroutine
7
7
  from typing import TYPE_CHECKING, Any, Generic, TypeVar, get_type_hints
8
8
 
9
9
  from pyobs.interfaces import Interface
10
+ from pyobs.utils.time import Time
10
11
 
11
12
  if TYPE_CHECKING:
12
13
  from pyobs.comm import Comm
@@ -172,9 +173,22 @@ class Proxy:
172
173
  """Clear all cached state. Called by Comm when the remote module disconnects."""
173
174
  self._state.clear()
174
175
 
175
- def get_state(self, interface: type[Interface]) -> Any | None:
176
- """Latest known state for the given interface, or None if nothing has arrived yet."""
177
- return self._state.get(interface)
176
+ def get_state(self, interface: type[Interface], *, max_age: float | None = None) -> Any | None:
177
+ """Latest known state for the given interface, or None if nothing has arrived yet
178
+ (or, with max_age given, if the latest known state is older than max_age seconds)."""
179
+ state = self._state.get(interface)
180
+ if state is None or max_age is None:
181
+ return state
182
+ return state if self._state_age(state) <= max_age else None
183
+
184
+ def _state_age(self, state: Any) -> float:
185
+ """Seconds since `state` (a State dataclass instance) was constructed by its publisher."""
186
+ t = getattr(state, "time", None)
187
+ if t is None:
188
+ raise ValueError(
189
+ f"{type(state).__name__} has no 'time' field -- max_age is not supported for this interface."
190
+ )
191
+ return (Time.now() - t).sec
178
192
 
179
193
  def update_capabilities(self, interface: type[Interface], capabilities: Any) -> None:
180
194
  """Called by Comm once capabilities for an interface arrive.
@@ -194,16 +208,22 @@ class Proxy:
194
208
  self,
195
209
  interface: type[Interface],
196
210
  timeout: float = 10.0,
211
+ *,
212
+ max_age: float | None = None,
197
213
  ) -> Any:
198
- """Return state immediately if available, otherwise wait for the first update.
214
+ """Return state immediately if available (and fresh enough per max_age), otherwise wait
215
+ for the next update.
199
216
 
200
217
  Returns None on timeout rather than raising -- every caller across the codebase already
201
218
  does `if state is not None else ...` right after calling this, so that's the contract
202
219
  actually being relied on; letting asyncio.wait_for's TimeoutError propagate would just
203
- turn "peer hasn't published yet" into an unhandled exception for all of them.
220
+ turn "peer hasn't published yet" into an unhandled exception for all of them. The same
221
+ None-on-"not usable yet" contract now also covers "published, but too stale" when max_age
222
+ is given.
204
223
  """
205
- if self._state.get(interface) is not None:
206
- return self._state[interface]
224
+ cached = self._state.get(interface)
225
+ if cached is not None and (max_age is None or self._state_age(cached) <= max_age):
226
+ return cached
207
227
 
208
228
  event = asyncio.Event()
209
229
 
@@ -220,7 +240,10 @@ class Proxy:
220
240
  finally:
221
241
  await self._comm.unsubscribe_state(self._client, interface, _notify)
222
242
 
223
- return self._state.get(interface)
243
+ result = self._state.get(interface)
244
+ if max_age is not None and result is not None and self._state_age(result) > max_age:
245
+ return None
246
+ return result
224
247
 
225
248
  async def wait_for_capabilities(
226
249
  self,
@@ -315,6 +315,14 @@ class XmppComm(Comm):
315
315
  self._xmpp.enable_direct_tls = self._use_tls
316
316
  self._xmpp.enable_plaintext = not self._use_tls
317
317
  self._xmpp.plugin["feature_mechanisms"].unencrypted_scram = not self._use_tls # type: ignore[typeddict-item]
318
+ # Without this, slixmpp still refuses PLAIN over a non-TLS connection even
319
+ # with enable_plaintext set above -- it only affects the stream feature
320
+ # advertisement, not SASL mechanism selection. Matters in practice: this
321
+ # server's SCRAM implementation fails unencrypted SCRAM auth with "Invalid
322
+ # channel binding" (confirmed against ejabberd 26.4.0), so without this
323
+ # flag every non-TLS connection falls through all mechanisms and fails
324
+ # with "No appropriate login method" rather than falling back to PLAIN.
325
+ self._xmpp.plugin["feature_mechanisms"].unencrypted_plain = not self._use_tls # type: ignore[typeddict-item]
318
326
  if self._ignore_cert_errors:
319
327
  self._xmpp.ssl_context.check_hostname = False
320
328
  self._xmpp.ssl_context.verify_mode = ssl.CERT_NONE
@@ -42,7 +42,7 @@ class Interface(metaclass=ABCMeta):
42
42
  )
43
43
  _REGISTRY[cls.__name__] = cls
44
44
 
45
- def get_state(self, interface: "type[Interface]") -> Any | None:
45
+ def get_state(self, interface: "type[Interface]", *, max_age: float | None = None) -> Any | None:
46
46
  """Return the last received state for the given interface, or None."""
47
47
  return None
48
48
 
@@ -50,7 +50,9 @@ class Interface(metaclass=ABCMeta):
50
50
  """Return the capabilities for the given interface, or None."""
51
51
  return None
52
52
 
53
- async def wait_for_state(self, interface: "type[Interface]", timeout: float = 10.0) -> Any | None:
53
+ async def wait_for_state(
54
+ self, interface: "type[Interface]", timeout: float = 10.0, *, max_age: float | None = None
55
+ ) -> Any | None:
54
56
  """Return state immediately if available, otherwise wait for the first update."""
55
57
  return None
56
58
 
@@ -18,8 +18,9 @@ class WeatherAwareMixin:
18
18
 
19
19
  __module__ = "pyobs.mixins"
20
20
 
21
- def __init__(self, weather: str | IWeather | None = None, **kwargs: Any):
21
+ def __init__(self, weather: str | IWeather | None = None, weather_max_age: float = 120.0, **kwargs: Any):
22
22
  self.__weather = weather
23
+ self.__weather_max_age = weather_max_age
23
24
  self.__is_weather_good: bool | None = None
24
25
  self.__last_park_attempt: float | None = None
25
26
  self.__weatheraware_is_error_state = False
@@ -121,7 +122,9 @@ class WeatherAwareMixin:
121
122
  try:
122
123
  # get good status
123
124
  async with module.proxy(this.__weather, IWeather) as proxy:
124
- weather_state = await proxy.wait_for_state(IWeather, timeout=5.0)
125
+ weather_state = await proxy.wait_for_state(
126
+ IWeather, timeout=5.0, max_age=this.__weather_max_age
127
+ )
125
128
  this.__is_weather_good = weather_state.good if weather_state is not None else False
126
129
  this.__weather_check_failures = 0
127
130
 
@@ -464,8 +464,11 @@ class BaseCamera(
464
464
  await asyncio.sleep(0.1)
465
465
 
466
466
  async def _abort_weather(self, event: Event, sender: str, **kwargs: Any) -> bool:
467
- """Abort on bad weather."""
468
- await self.abort()
467
+ """Abort on bad weather, unless the shutter is closed (dark/bias) -- those don't
468
+ expose anything to the weather, and image_type is fixed for a whole sequence, so
469
+ this also lets an in-progress dark/bias sequence run to completion undisturbed."""
470
+ if self._image_type not in (ImageType.BIAS, ImageType.DARK):
471
+ await self.abort()
469
472
  return True
470
473
 
471
474
  @staticmethod
@@ -153,6 +153,12 @@ class DummyCamera(BaseCamera, IWindow, IBinning, ICooling, IGain, IImageFormat):
153
153
  ICooling,
154
154
  CoolingState(setpoint=self._cooling.set_point, power=self._cooling.power, enabled=self._cooling.enabled),
155
155
  )
156
+ await self.comm.set_state(
157
+ ITemperatures,
158
+ TemperaturesState(
159
+ readings=[SensorReading(name=name, value=value) for name, value in self._cooling.temperatures.items()]
160
+ ),
161
+ )
156
162
  await self.comm.set_state(IGain, GainState(gain=self._gain, offset=self._gain_offset))
157
163
  await self.comm.set_state(IWindow, WindowState(*self._full_frame))
158
164
  await self.comm.set_state(IBinning, BinningState(*self._binning))
@@ -106,14 +106,6 @@ class FlatField(Module, IFlatField, IBinning, IFilters):
106
106
  """Open module"""
107
107
  await Module.open(self)
108
108
 
109
- # check telescope, camera, and filters
110
- if (
111
- not await self.has_proxy(self._telescope, ITelescope)
112
- or not await self.has_proxy(self._camera, ICamera)
113
- or not await self.has_proxy(self._filter_wheel, IFilters)
114
- ):
115
- log.warning("Either telescope, camera or filters do not exist or are not of correct type at the moment.")
116
-
117
109
  # subscribe to events
118
110
  if self._comm:
119
111
  await self.comm.register_event(BadWeatherEvent, self._abort_weather)
@@ -68,14 +68,6 @@ class FlatFieldScheduler(Module, IRunnable):
68
68
  count=count,
69
69
  )
70
70
 
71
- async def open(self) -> None:
72
- """Open module"""
73
- await Module.open(self)
74
-
75
- # check flat field
76
- if not await self.has_proxy(self._flatfield, IFlatField):
77
- log.warning("Flatfield module does not exist or is not of correct type at the moment.")
78
-
79
71
  @timeout(7200)
80
72
  async def run(self, **kwargs: Any) -> None:
81
73
  """Perform flat-fielding
@@ -95,10 +95,6 @@ class AutoFocusSeries(Module, CameraSettingsMixin, IAutoFocus):
95
95
  await self.comm.register_event(FocusFoundEvent)
96
96
  await self.comm.register_event(BadWeatherEvent, self._on_bad_weather)
97
97
 
98
- # check focuser and camera
99
- if not await self.has_proxy(self._focuser, IFocuser) or not await self.has_proxy(self._camera, IData):
100
- log.warning("Either camera or focuser do not exist or are not of correct type at the moment.")
101
-
102
98
  # publish initial states
103
99
  await self.comm.set_state(IAutoFocus, AutoFocusState())
104
100
  await self.comm.set_state(IRunning, RunningState(running=False))
@@ -344,6 +344,17 @@ class Module(Object, IModule, IConfig):
344
344
  which would then never leave STARTING under Application/MultiModule.
345
345
  """
346
346
  await self.open()
347
+
348
+ # warn if any stateful interface hasn't published state yet
349
+ if self._comm is not None:
350
+ missing = self._comm.missing_published_state(self._interfaces)
351
+ for iface in missing:
352
+ log.warning(
353
+ "Module %s implements %s which declares state, but no state has been published for it yet.",
354
+ self.name,
355
+ iface.__name__,
356
+ )
357
+
347
358
  await self.set_state(ModuleState.READY)
348
359
 
349
360
  async def close(self) -> None:
@@ -57,17 +57,5 @@ class BasePointing(Module, PipelineMixin, metaclass=ABCMeta):
57
57
  exc.RemoteError, 3, timespan=600, module=telescope, callback=self._default_remote_error_callback
58
58
  )
59
59
 
60
- async def open(self) -> None:
61
- """Open module."""
62
- await Module.open(self)
63
-
64
- # check telescope
65
- if not await self.has_proxy(self._telescope, ITelescope):
66
- log.warning("Given telescope does not exist or is not of correct type at the moment.")
67
-
68
- # check camera
69
- if not await self.has_proxy(self._camera, ICamera):
70
- log.warning("Given camera does not exist or is not of correct type at the moment.")
71
-
72
60
 
73
61
  __all__ = ["BasePointing"]
@@ -99,12 +99,6 @@ class Acquisition(BasePointing, CameraSettingsMixin, IAcquisition):
99
99
  """Open module"""
100
100
  await Module.open(self)
101
101
 
102
- # check telescope and camera
103
- if not await self.has_proxy(self._telescope, ITelescope):
104
- log.warning("Telescope does not exist or is not of correct type at the moment.")
105
- if not await self.has_proxy(self._camera, ICamera):
106
- log.warning("Camera does not exist or is not of correct type at the moment.")
107
-
108
102
  # publish initial states
109
103
  await self.comm.set_state(IAcquisition, AcquisitionState())
110
104
  await self.comm.set_state(IRunning, RunningState(running=False))
@@ -93,6 +93,7 @@ class Weather(Module, IWeather, IFitsHeaderBefore):
93
93
  await self.comm.register_event(GoodWeatherEvent)
94
94
 
95
95
  await self.comm.set_state(IRunning, RunningState(running=self._active))
96
+ await self._publish_state()
96
97
 
97
98
  async def start(self, **kwargs: Any) -> None:
98
99
  """Starts a service."""
@@ -150,6 +151,9 @@ class Weather(Module, IWeather, IFitsHeaderBefore):
150
151
  await self.comm.send_event(BadWeatherEvent())
151
152
 
152
153
  # publish state
154
+ await self._publish_state()
155
+
156
+ async def _publish_state(self) -> None:
153
157
  is_good = True if not self._active else self._weather.is_good
154
158
  await self.comm.set_state(IWeather, WeatherState(good=is_good, readings=self._get_readings()))
155
159
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pyobs-core"
3
- version = "2.0.0.dev41"
3
+ version = "2.0.0.dev43"
4
4
  description = "robotic telescope software"
5
5
  authors = [{ name = "Tim-Oliver Husser", email = "thusser@uni-goettingen.de" }]
6
6
  requires-python = ">=3.11"