pyobs-core 2.0.0.dev43__tar.gz → 2.0.0.dev45__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.dev43 → pyobs_core-2.0.0.dev45}/PKG-INFO +1 -1
  2. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/application.py +9 -1
  3. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/cli/pyobsd.py +13 -3
  4. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/comm/comm.py +4 -1
  5. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/comm/commlogging.py +6 -0
  6. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/comm/dummy/dummycomm.py +13 -5
  7. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IRunning.py +1 -7
  8. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/mixins/follow.py +16 -4
  9. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/focus/dummyautofocus.py +0 -4
  10. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/focus/focusmodel.py +17 -7
  11. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/focus/focusseries.py +0 -4
  12. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/pointing/_baseguiding.py +0 -8
  13. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/pointing/acquisition.py +0 -4
  14. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/pointing/dummyacquisition.py +0 -4
  15. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/pointing/dummyguiding.py +0 -3
  16. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/robotic/mastermind.py +0 -4
  17. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/robotic/pointing.py +1 -5
  18. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/robotic/scheduler.py +0 -4
  19. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/utils/kiosk.py +0 -4
  20. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/utils/trigger.py +0 -4
  21. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/weather/mockweather.py +0 -4
  22. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/weather/weather.py +0 -4
  23. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyproject.toml +1 -1
  24. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/.gitignore +0 -0
  25. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/LICENSE +0 -0
  26. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/__init__.py +0 -0
  27. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/background_task.py +0 -0
  28. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/cli/__init__.py +0 -0
  29. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/cli/_cli.py +0 -0
  30. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/cli/pyobs.py +0 -0
  31. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/cli/pyobsw.py +0 -0
  32. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/comm/__init__.py +0 -0
  33. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/comm/dummy/__init__.py +0 -0
  34. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/comm/local/__init__.py +0 -0
  35. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/comm/local/localcomm.py +0 -0
  36. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/comm/local/localnetwork.py +0 -0
  37. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/comm/proxy.py +0 -0
  38. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/comm/xmpp/__init__.py +0 -0
  39. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/comm/xmpp/rpc.py +0 -0
  40. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/comm/xmpp/serializer.py +0 -0
  41. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/comm/xmpp/xep_0009/__init__.py +0 -0
  42. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/comm/xmpp/xep_0009/binding.py +0 -0
  43. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/comm/xmpp/xep_0009/rpc.py +0 -0
  44. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/comm/xmpp/xep_0009_timeout/__init__.py +0 -0
  45. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/comm/xmpp/xep_0009_timeout/rpc.py +0 -0
  46. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/comm/xmpp/xep_0009_timeout/stanza/RPC.py +0 -0
  47. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/comm/xmpp/xep_0009_timeout/stanza/__init__.py +0 -0
  48. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/comm/xmpp/xmppclient.py +0 -0
  49. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/comm/xmpp/xmppcomm.py +0 -0
  50. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/events/__init__.py +0 -0
  51. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/events/badweather.py +0 -0
  52. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/events/event.py +0 -0
  53. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/events/exposurestatuschanged.py +0 -0
  54. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/events/filterchanged.py +0 -0
  55. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/events/focusfound.py +0 -0
  56. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/events/goodweather.py +0 -0
  57. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/events/log.py +0 -0
  58. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/events/modechanged.py +0 -0
  59. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/events/moduleclosed.py +0 -0
  60. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/events/moduleopened.py +0 -0
  61. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/events/motionstatuschanged.py +0 -0
  62. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/events/move.py +0 -0
  63. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/events/newimage.py +0 -0
  64. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/events/newspectrum.py +0 -0
  65. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/events/offsets.py +0 -0
  66. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/events/roofclosing.py +0 -0
  67. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/events/roofopened.py +0 -0
  68. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/events/taskfailed.py +0 -0
  69. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/events/taskfinished.py +0 -0
  70. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/events/taskstarted.py +0 -0
  71. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/events/testevent.py +0 -0
  72. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/__init__.py +0 -0
  73. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/image.py +0 -0
  74. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/meta/__init__.py +0 -0
  75. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/meta/altazoffsets.py +0 -0
  76. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/meta/exptime.py +0 -0
  77. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/meta/genericoffset.py +0 -0
  78. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/meta/onskydistance.py +0 -0
  79. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/meta/pixeloffsets.py +0 -0
  80. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/meta/radecoffsets.py +0 -0
  81. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/meta/skyoffsets.py +0 -0
  82. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processor.py +0 -0
  83. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/__init__.py +0 -0
  84. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/_daobackgroundremover.py +0 -0
  85. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/annotation/__init__.py +0 -0
  86. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/annotation/_pillow.py +0 -0
  87. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/annotation/circle.py +0 -0
  88. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/annotation/crosshair.py +0 -0
  89. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/annotation/text.py +0 -0
  90. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/astrometry/__init__.py +0 -0
  91. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/astrometry/_dotnet_request.py +0 -0
  92. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/astrometry/_dotnet_request_builder.py +0 -0
  93. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/astrometry/_dotnet_request_logger.py +0 -0
  94. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/astrometry/_dotnet_response_saver.py +0 -0
  95. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/astrometry/astrometry.py +0 -0
  96. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/astrometry/dotnet.py +0 -0
  97. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/calibration/__init__.py +0 -0
  98. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/calibration/_calibration_cache.py +0 -0
  99. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/calibration/_ccddata_calibrator.py +0 -0
  100. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/calibration/calibration.py +0 -0
  101. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/detection/__init__.py +0 -0
  102. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/detection/_pysep_stats_calculator.py +0 -0
  103. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/detection/_source_catalog.py +0 -0
  104. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/detection/daophot.py +0 -0
  105. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/detection/pysep.py +0 -0
  106. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/detection/simpledisk.py +0 -0
  107. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/detection/sourcedetection.py +0 -0
  108. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/exptime/__init__.py +0 -0
  109. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/exptime/exptime.py +0 -0
  110. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/exptime/star.py +0 -0
  111. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/image/__init__.py +0 -0
  112. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/image/addfitsheaders.py +0 -0
  113. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/image/download.py +0 -0
  114. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/image/flip.py +0 -0
  115. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/image/grayscale.py +0 -0
  116. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/image/httpserver.py +0 -0
  117. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/image/normalize.py +0 -0
  118. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/image/save.py +0 -0
  119. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/image/saveimage.py +0 -0
  120. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/image/smooth.py +0 -0
  121. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/image/softbin.py +0 -0
  122. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/misc/__init__.py +0 -0
  123. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/misc/addmask.py +0 -0
  124. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/misc/catalogcircularmask.py +0 -0
  125. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/misc/circularmask.py +0 -0
  126. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/misc/createfilename.py +0 -0
  127. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/misc/imagesourcefilter.py +0 -0
  128. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/misc/removebackground.py +0 -0
  129. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/modules/__init__.py +0 -0
  130. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/modules/getfitsheaders.py +0 -0
  131. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/offsets/__init__.py +0 -0
  132. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/offsets/astrometry.py +0 -0
  133. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/offsets/brighteststar.py +0 -0
  134. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/offsets/brighteststar_guiding.py +0 -0
  135. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/offsets/dummyoffsets.py +0 -0
  136. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/offsets/dummyskyoffsets.py +0 -0
  137. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/offsets/fitsheader.py +0 -0
  138. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/offsets/offsets.py +0 -0
  139. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/offsets/pixeloffsets.py +0 -0
  140. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/offsets/projected.py +0 -0
  141. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/offsets/spilled_light.py +0 -0
  142. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/photometry/__init__.py +0 -0
  143. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/photometry/_photometry_calculator.py +0 -0
  144. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/photometry/_photutil_aperture_photometry.py +0 -0
  145. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/photometry/_sep_aperture_photometry.py +0 -0
  146. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/photometry/aperture_photometry.py +0 -0
  147. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/photometry/photometry.py +0 -0
  148. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/photometry/photutil.py +0 -0
  149. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/photometry/pysep.py +0 -0
  150. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/wcs/__init__.py +0 -0
  151. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/images/processors/wcs/solarhelioprojective.py +0 -0
  152. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IAbortable.py +0 -0
  153. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IAcquisition.py +0 -0
  154. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IAutoFocus.py +0 -0
  155. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IAutoGuiding.py +0 -0
  156. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IAutonomous.py +0 -0
  157. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IBinning.py +0 -0
  158. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/ICalibrate.py +0 -0
  159. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/ICamera.py +0 -0
  160. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IConfig.py +0 -0
  161. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/ICooling.py +0 -0
  162. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IData.py +0 -0
  163. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IDataSequence.py +0 -0
  164. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IDome.py +0 -0
  165. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IExposure.py +0 -0
  166. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IExposureTime.py +0 -0
  167. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IFilters.py +0 -0
  168. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IFitsHeaderAfter.py +0 -0
  169. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IFitsHeaderBefore.py +0 -0
  170. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IFlatField.py +0 -0
  171. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IFocusModel.py +0 -0
  172. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IFocuser.py +0 -0
  173. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IGain.py +0 -0
  174. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IImageFormat.py +0 -0
  175. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IImageType.py +0 -0
  176. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IMode.py +0 -0
  177. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IModule.py +0 -0
  178. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IMotion.py +0 -0
  179. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IMultiFiber.py +0 -0
  180. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IOffsetsAltAz.py +0 -0
  181. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IOffsetsRaDec.py +0 -0
  182. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IPointingAltAz.py +0 -0
  183. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IPointingBody.py +0 -0
  184. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IPointingHeliocentricPolar.py +0 -0
  185. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IPointingHeliographicStonyhurst.py +0 -0
  186. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IPointingHelioprojective.py +0 -0
  187. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IPointingOrbitalElements.py +0 -0
  188. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IPointingRaDec.py +0 -0
  189. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IPointingSeries.py +0 -0
  190. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IReady.py +0 -0
  191. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IRoof.py +0 -0
  192. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IRotation.py +0 -0
  193. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IRunnable.py +0 -0
  194. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IScriptRunner.py +0 -0
  195. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/ISpectrograph.py +0 -0
  196. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IStartStop.py +0 -0
  197. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IStructuredConfig.py +0 -0
  198. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/ISyncTarget.py +0 -0
  199. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/ITelescope.py +0 -0
  200. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/ITemperatures.py +0 -0
  201. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/ITrackingMode.py +0 -0
  202. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/ITrackingRate.py +0 -0
  203. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IVideo.py +0 -0
  204. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IWeather.py +0 -0
  205. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/IWindow.py +0 -0
  206. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/__init__.py +0 -0
  207. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/interfaces/interface.py +0 -0
  208. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/mixins/__init__.py +0 -0
  209. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/mixins/camerasettings.py +0 -0
  210. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/mixins/fitsheader.py +0 -0
  211. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/mixins/fitsnamespace.py +0 -0
  212. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/mixins/motionstatus.py +0 -0
  213. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/mixins/pipeline.py +0 -0
  214. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/mixins/waitformotion.py +0 -0
  215. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/mixins/weatheraware.py +0 -0
  216. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/__init__.py +0 -0
  217. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/camera/__init__.py +0 -0
  218. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/camera/adaptive.py +0 -0
  219. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/camera/basecamera.py +0 -0
  220. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/camera/basespectrograph.py +0 -0
  221. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/camera/basevideo.py +0 -0
  222. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/camera/dummycamera.py +0 -0
  223. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/camera/dummyspectrograph.py +0 -0
  224. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/camera/dummyvideo.py +0 -0
  225. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/camera/pipelinecamera.py +0 -0
  226. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/flatfield/__init__.py +0 -0
  227. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/flatfield/flatfield.py +0 -0
  228. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/flatfield/pointing.py +0 -0
  229. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/flatfield/scheduler.py +0 -0
  230. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/focus/__init__.py +0 -0
  231. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/image/__init__.py +0 -0
  232. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/image/imagewatcher.py +0 -0
  233. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/image/imagewriter.py +0 -0
  234. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/image/pipeline.py +0 -0
  235. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/image/seeing.py +0 -0
  236. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/module.py +0 -0
  237. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/pointing/__init__.py +0 -0
  238. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/pointing/_base.py +0 -0
  239. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/pointing/autoguiding.py +0 -0
  240. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/pointing/guidingstatistics/__init__.py +0 -0
  241. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/pointing/guidingstatistics/guidingstatistics.py +0 -0
  242. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/pointing/guidingstatistics/pixeloffset.py +0 -0
  243. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/pointing/guidingstatistics/skyoffsets.py +0 -0
  244. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/pointing/guidingstatistics/uptime.py +0 -0
  245. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/pointing/scienceframeguiding.py +0 -0
  246. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/robotic/__init__.py +0 -0
  247. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/robotic/scriptrunner.py +0 -0
  248. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/roof/__init__.py +0 -0
  249. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/roof/basedome.py +0 -0
  250. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/roof/baseroof.py +0 -0
  251. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/roof/dummyroof.py +0 -0
  252. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/telescope/__init__.py +0 -0
  253. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/telescope/_dummytelescopebase.py +0 -0
  254. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/telescope/basetelescope.py +0 -0
  255. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/telescope/dummyaltaztelescope.py +0 -0
  256. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/telescope/dummyradectelescope.py +0 -0
  257. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/telescope/dummysolartelescope.py +0 -0
  258. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/test/__init__.py +0 -0
  259. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/test/standalone.py +0 -0
  260. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/utils/__init__.py +0 -0
  261. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/utils/dummymode.py +0 -0
  262. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/utils/fluentlogger.py +0 -0
  263. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/utils/httpfilecache.py +0 -0
  264. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/utils/matrix.py +0 -0
  265. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/utils/stellarium.py +0 -0
  266. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/utils/telegram.py +0 -0
  267. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/weather/__init__.py +0 -0
  268. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/weather/weather_api.py +0 -0
  269. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/modules/weather/weather_state.py +0 -0
  270. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/object.py +0 -0
  271. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/py.typed +0 -0
  272. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/__init__.py +0 -0
  273. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/observation.py +0 -0
  274. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/__init__.py +0 -0
  275. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/astroplanscheduler.py +0 -0
  276. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/constraints/__init__.py +0 -0
  277. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/constraints/airmassconstraint.py +0 -0
  278. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/constraints/constraint.py +0 -0
  279. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/constraints/moonilluminationconstraint.py +0 -0
  280. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/constraints/moonseparationconstraint.py +0 -0
  281. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/constraints/solarelevationconstraint.py +0 -0
  282. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/constraints/timeconstraint.py +0 -0
  283. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/dataprovider.py +0 -0
  284. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/merits/__init__.py +0 -0
  285. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/merits/aftertime.py +0 -0
  286. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/merits/beforetime.py +0 -0
  287. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/merits/constant.py +0 -0
  288. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/merits/follow.py +0 -0
  289. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/merits/interval.py +0 -0
  290. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/merits/merit.py +0 -0
  291. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/merits/pernight.py +0 -0
  292. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/merits/random.py +0 -0
  293. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/merits/timewindow.py +0 -0
  294. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/merits/transit.py +0 -0
  295. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/observationarchiveevolution.py +0 -0
  296. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/ondemandscheduler.py +0 -0
  297. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/targets/__init__.py +0 -0
  298. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/targets/dynamictarget.py +0 -0
  299. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/targets/heliocentricpolartarget.py +0 -0
  300. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/targets/helioprojectivetarget.py +0 -0
  301. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/targets/picker/__init__.py +0 -0
  302. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/targets/picker/csvpicker.py +0 -0
  303. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/targets/picker/picker.py +0 -0
  304. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/targets/siderealtarget.py +0 -0
  305. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/targets/target.py +0 -0
  306. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scheduler/taskscheduler.py +0 -0
  307. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scripts/__init__.py +0 -0
  308. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scripts/calibration/__init__.py +0 -0
  309. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scripts/calibration/darkbias.py +0 -0
  310. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scripts/calibration/pointing.py +0 -0
  311. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scripts/calibration/skyflats.py +0 -0
  312. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scripts/control/__init__.py +0 -0
  313. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scripts/control/cases.py +0 -0
  314. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scripts/control/conditional.py +0 -0
  315. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scripts/control/parallel.py +0 -0
  316. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scripts/control/selector.py +0 -0
  317. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scripts/control/sequential.py +0 -0
  318. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scripts/exceptions.py +0 -0
  319. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scripts/imaging/__init__.py +0 -0
  320. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scripts/imaging/autofocus.py +0 -0
  321. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scripts/imaging/imaging.py +0 -0
  322. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scripts/imaging/transitimaging.py +0 -0
  323. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scripts/script.py +0 -0
  324. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scripts/utils/__init__.py +0 -0
  325. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scripts/utils/callmodule.py +0 -0
  326. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scripts/utils/debugtrigger.py +0 -0
  327. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/scripts/utils/log.py +0 -0
  328. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/__init__.py +0 -0
  329. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/backend/__init__.py +0 -0
  330. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/backend/observationarchive.py +0 -0
  331. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/backend/taskarchive.py +0 -0
  332. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/filesystem/__init__.py +0 -0
  333. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/filesystem/observationarchive.py +0 -0
  334. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/filesystem/taskarchive.py +0 -0
  335. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/lco/__init__.py +0 -0
  336. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/lco/_portal.py +0 -0
  337. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/lco/_schedulereader.py +0 -0
  338. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/lco/_schedulewriter.py +0 -0
  339. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/lco/configdb.py +0 -0
  340. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/lco/mockobservationarchive.py +0 -0
  341. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/lco/observationarchive.py +0 -0
  342. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/lco/scripts/__init__.py +0 -0
  343. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/lco/scripts/autofocus.py +0 -0
  344. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/lco/scripts/default.py +0 -0
  345. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/lco/scripts/script.py +0 -0
  346. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/lco/task.py +0 -0
  347. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/lco/taskarchive.py +0 -0
  348. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/lco/taskrunner.py +0 -0
  349. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/memory/__init__.py +0 -0
  350. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/memory/observationarchive.py +0 -0
  351. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/memory/taskarchive.py +0 -0
  352. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/observationarchive.py +0 -0
  353. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/storage/taskarchive.py +0 -0
  354. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/task.py +0 -0
  355. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/taskrunner.py +0 -0
  356. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/utils/__init__.py +0 -0
  357. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/utils/archive/__init__.py +0 -0
  358. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/utils/archive/archive.py +0 -0
  359. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/utils/archive/local_archive.py +0 -0
  360. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/utils/archive/pyobs_archive.py +0 -0
  361. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/utils/exptime/__init__.py +0 -0
  362. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/utils/exptime/exptime.py +0 -0
  363. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/utils/exptime/stellarexptime.py +0 -0
  364. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/utils/skyflats/__init__.py +0 -0
  365. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/utils/skyflats/exptimeeval.py +0 -0
  366. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/utils/skyflats/flatfielder.py +0 -0
  367. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/utils/skyflats/pointing/__init__.py +0 -0
  368. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/utils/skyflats/pointing/base.py +0 -0
  369. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/utils/skyflats/pointing/static.py +0 -0
  370. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/utils/skyflats/priorities/__init__.py +0 -0
  371. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/utils/skyflats/priorities/archive.py +0 -0
  372. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/utils/skyflats/priorities/base.py +0 -0
  373. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/utils/skyflats/priorities/const.py +0 -0
  374. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/robotic/utils/skyflats/scheduler.py +0 -0
  375. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/__init__.py +0 -0
  376. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/average.py +0 -0
  377. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/cache.py +0 -0
  378. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/config.py +0 -0
  379. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/config_schema.py +0 -0
  380. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/coordinates.py +0 -0
  381. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/curvefit.py +0 -0
  382. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/enums.py +0 -0
  383. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/exceptions.py +0 -0
  384. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/fits.py +0 -0
  385. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/focusseries/__init__.py +0 -0
  386. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/focusseries/base.py +0 -0
  387. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/focusseries/photometry.py +0 -0
  388. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/focusseries/projection.py +0 -0
  389. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/grids/__init__.py +0 -0
  390. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/grids/filters.py +0 -0
  391. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/grids/grid.py +0 -0
  392. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/grids/gridnode.py +0 -0
  393. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/grids/pipeline.py +0 -0
  394. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/gui/__init__.py +0 -0
  395. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/gui/camera/__init__.py +0 -0
  396. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/gui/camera/binningwidget.py +0 -0
  397. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/gui/camera/datadisplaywidget.py +0 -0
  398. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/gui/camera/exposewidget.py +0 -0
  399. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/gui/camera/exposuretimewidget.py +0 -0
  400. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/gui/camera/imageformatwidget.py +0 -0
  401. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/gui/camera/listpickerdialog.py +0 -0
  402. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/gui/camera/windowingwidget.py +0 -0
  403. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/http.py +0 -0
  404. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/influxdb.py +0 -0
  405. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/logger.py +0 -0
  406. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/logging/__init__.py +0 -0
  407. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/logging/context.py +0 -0
  408. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/logging/resolvableerror.py +0 -0
  409. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/modulegui.py +0 -0
  410. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/offsets/__init__.py +0 -0
  411. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/offsets/applyaltazoffsets.py +0 -0
  412. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/offsets/applyoffsets.py +0 -0
  413. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/offsets/applyradecoffsets.py +0 -0
  414. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/parallel.py +0 -0
  415. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/pipeline/__init__.py +0 -0
  416. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/pipeline/night.py +0 -0
  417. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/pipeline/pipeline.py +0 -0
  418. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/publisher/__init__.py +0 -0
  419. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/publisher/csv.py +0 -0
  420. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/publisher/http.py +0 -0
  421. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/publisher/log.py +0 -0
  422. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/publisher/multi.py +0 -0
  423. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/publisher/publisher.py +0 -0
  424. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/serialization.py +0 -0
  425. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/shellcommand.py +0 -0
  426. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/threads/__init__.py +0 -0
  427. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/threads/lockwithabort.py +0 -0
  428. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/time.py +0 -0
  429. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/utils/units.py +0 -0
  430. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/version.py +0 -0
  431. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/vfs/__init__.py +0 -0
  432. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/vfs/archivefile.py +0 -0
  433. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/vfs/bufferedfile.py +0 -0
  434. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/vfs/file.py +0 -0
  435. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/vfs/filelists/__init__.py +0 -0
  436. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/vfs/filelists/filelist.py +0 -0
  437. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/vfs/filelists/testing.py +0 -0
  438. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/vfs/httpfile.py +0 -0
  439. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/vfs/localfile.py +0 -0
  440. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/vfs/memfile.py +0 -0
  441. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/vfs/sftpfile.py +0 -0
  442. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/vfs/smbfile.py +0 -0
  443. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/vfs/sshfile.py +0 -0
  444. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/pyobs/vfs/tempfile.py +0 -0
  445. {pyobs_core-2.0.0.dev43 → pyobs_core-2.0.0.dev45}/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.dev43
3
+ Version: 2.0.0.dev45
4
4
  Summary: robotic telescope software
5
5
  Author-email: Tim-Oliver Husser <thusser@uni-goettingen.de>
6
6
  License-Expression: MIT
@@ -10,6 +10,7 @@ from typing import Any, TypedDict
10
10
 
11
11
  import yaml
12
12
 
13
+ from pyobs.comm.dummy import DummyComm
13
14
  from pyobs.modules import Module, MultiModule
14
15
  from pyobs.object import get_class_from_string, get_object
15
16
  from pyobs.utils.config import pre_process_yaml
@@ -181,6 +182,14 @@ class Application:
181
182
  asyncio.set_event_loop(self._loop)
182
183
 
183
184
  # create module and open it
185
+ config_stem = Path(self._config).stem.lstrip("_")
186
+ if "comm" not in cfg and not issubclass(klass, MultiModule):
187
+ # no comm configured -- module would otherwise fall back to a DummyComm named
188
+ # with the fixed placeholder "module", indistinguishable from every other
189
+ # comm-less module in PYOBS_MODULE log tagging (see
190
+ # specs/steering/finding-module-logs-under-pyobsd.md) and guaranteed to trip the
191
+ # stem-mismatch check below. Give it the config file's own stem instead.
192
+ cfg = {**cfg, "comm": {"class": f"{DummyComm.__module__}.{DummyComm.__name__}", "name": config_stem}}
184
193
  log.info("Creating module from class %s...", klass.__name__)
185
194
  self._module = get_object(cfg, Module)
186
195
 
@@ -193,7 +202,6 @@ class Application:
193
202
  # (module.py), never meant to match a filename -- each child module is already
194
203
  # correctly distinguished via execute()/BackgroundTask.
195
204
  if not isinstance(self._module, MultiModule):
196
- config_stem = Path(self._config).stem.lstrip("_")
197
205
  if self._module.name != config_stem:
198
206
  log.warning(
199
207
  "Config file stem (%s) does not match module's own name "
@@ -33,6 +33,7 @@ class PyobsDaemonCLI(CLI):
33
33
  "log_path",
34
34
  "log_level",
35
35
  "syslog",
36
+ "file_log",
36
37
  "chuid",
37
38
  ]
38
39
 
@@ -54,6 +55,12 @@ class PyobsDaemonCLI(CLI):
54
55
  help="send module logs to systemd journal (use --no-syslog to disable)",
55
56
  default=self._config.get("syslog", True),
56
57
  )
58
+ self._parser.add_argument(
59
+ "--file-log",
60
+ action=argparse.BooleanOptionalAction,
61
+ help="also write each module's log to <log-path>/<module>.log (off by default; use --file-log to enable)",
62
+ default=self._config.get("file_log", False),
63
+ )
57
64
  self._parser.add_argument("--chuid", type=str, default=self._config.get("chuid", "pyobs:pyobs"))
58
65
  self._parser.add_argument("-v", "--verbose", action="store_true")
59
66
 
@@ -76,6 +83,7 @@ class PyobsDaemonCLI(CLI):
76
83
  str(os.path.join(self._config["path"], self._config["log_path"])),
77
84
  log_level=self._config["log_level"],
78
85
  syslog=self._config["syslog"],
86
+ file_log=self._config["file_log"],
79
87
  chuid=self._config["chuid"],
80
88
  verbose=self._config["verbose"],
81
89
  )
@@ -104,6 +112,7 @@ class PyobsDaemon:
104
112
  log_path: str,
105
113
  log_level: str = "info",
106
114
  syslog: bool = False,
115
+ file_log: bool = False,
107
116
  chuid: str | None = None,
108
117
  verbose: bool = False,
109
118
  **kwargs: Any,
@@ -113,6 +122,7 @@ class PyobsDaemon:
113
122
  self._log_path = log_path
114
123
  self._log_level = log_level
115
124
  self._syslog = syslog
125
+ self._file_log = file_log
116
126
  self._verbose = verbose
117
127
 
118
128
  # parse optional user/group from chuid (format: "user:group" or "user")
@@ -317,18 +327,18 @@ class PyobsDaemon:
317
327
 
318
328
  def _start_service(self, module: str) -> None:
319
329
  os.makedirs(self._run_path, exist_ok=True)
320
- os.makedirs(self._log_path, exist_ok=True)
321
330
 
322
331
  cmd = [
323
332
  self._pyobs_exec,
324
333
  "--pid-file",
325
334
  self._pid_file(module),
326
- "--log-file",
327
- self._log_file(module),
328
335
  "--log-level",
329
336
  self._log_level,
330
337
  self._config_file(module),
331
338
  ]
339
+ if self._file_log:
340
+ os.makedirs(self._log_path, exist_ok=True)
341
+ cmd += ["--log-file", self._log_file(module)]
332
342
  if self._syslog:
333
343
  cmd.append("--syslog")
334
344
 
@@ -382,7 +382,10 @@ class Comm:
382
382
  return
383
383
 
384
384
  except Exception:
385
- log.exception("Something went wrong")
385
+ # don't forward this back through CommLoggingHandler -- it would re-queue
386
+ # itself onto _log_queue, and if the send failure is due to a sustained
387
+ # outage, every retry generates another one of these, forever
388
+ log.exception("Something went wrong", extra={"pyobs_no_forward": True})
386
389
  pass
387
390
 
388
391
  def log_message(self, entry: LogEvent) -> None:
@@ -31,6 +31,12 @@ class CommLoggingHandler(logging.Handler):
31
31
  rec: Log record to send.
32
32
  """
33
33
 
34
+ # a record about the forwarding pipeline itself failing (e.g. Comm._logging's own
35
+ # send failure) must not be forwarded again, or a sustained outage turns into an
36
+ # unbounded loop of "failed to send" records about failing to send that record
37
+ if getattr(rec, "pyobs_no_forward", False):
38
+ return
39
+
34
40
  # format message
35
41
  msg = self._formatter.format(rec) # noqa: UP031
36
42
 
@@ -14,9 +14,17 @@ log = logging.getLogger(__name__)
14
14
  class DummyComm(Comm):
15
15
  """A dummy implementation of the Comm interface."""
16
16
 
17
- def __init__(self, *args: Any, **kwargs: Any):
18
- """Creates a new dummy comm."""
17
+ def __init__(self, name: str = "module", *args: Any, **kwargs: Any):
18
+ """Creates a new dummy comm.
19
+
20
+ Args:
21
+ name: Name to report for this comm. Defaults to the generic placeholder "module"
22
+ for callers (e.g. tests) that construct a DummyComm directly without a real
23
+ identity; Application fills in the config file's stem when a module has no
24
+ comm of its own configured.
25
+ """
19
26
  Comm.__init__(self, *args, **kwargs)
27
+ self._name = name
20
28
 
21
29
  @property
22
30
  def clients(self) -> list[str]:
@@ -47,8 +55,8 @@ class DummyComm(Comm):
47
55
 
48
56
  @property
49
57
  def name(self) -> str:
50
- """Name of this client, which is unknown."""
51
- return "module"
58
+ """Name of this client."""
59
+ return self._name
52
60
 
53
61
  async def send_event(self, event: Event) -> None:
54
62
  """Send an event to other clients.
@@ -56,7 +64,7 @@ class DummyComm(Comm):
56
64
  Args:
57
65
  event (Event): Event to send
58
66
  """
59
- self._send_event_to_module(event, "module")
67
+ self._send_event_to_module(event, self._name)
60
68
 
61
69
 
62
70
  __all__ = ["DummyComm"]
@@ -1,8 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
- from abc import ABCMeta, abstractmethod
3
+ from abc import ABCMeta
4
4
  from dataclasses import dataclass, field
5
- from typing import Any
6
5
 
7
6
  from ..utils.time import Time
8
7
  from .interface import Interface
@@ -21,10 +20,5 @@ class IRunning(Interface, metaclass=ABCMeta):
21
20
 
22
21
  state = RunningState
23
22
 
24
- @abstractmethod
25
- async def is_running(self, **kwargs: Any) -> bool:
26
- """Whether a service is running."""
27
- ...
28
-
29
23
 
30
24
  __all__ = ["IRunning", "RunningState"]
@@ -15,13 +15,18 @@ log = logging.getLogger(__name__)
15
15
 
16
16
 
17
17
  async def get_coords(
18
- obj: IPointingAltAz | IPointingRaDec, mode: type[IPointingAltAz | IPointingRaDec]
18
+ obj: IPointingAltAz | IPointingRaDec,
19
+ mode: type[IPointingAltAz | IPointingRaDec],
20
+ max_age: float | None = None,
19
21
  ) -> tuple[float, float]:
20
22
  """Gets coordinates from object
21
23
 
22
24
  Args:
23
25
  obj: Object to fetch coordinates from.
24
26
  mode: IAltAz or IRaDec.
27
+ max_age: If obj is a remote Proxy, treat cached state older than this many seconds the
28
+ same as "not available" (raises ValueError below). Ignored for a Module, whose own
29
+ state is always current from its own perspective.
25
30
 
26
31
  Returns:
27
32
  Return from method call.
@@ -29,7 +34,7 @@ async def get_coords(
29
34
 
30
35
  if mode == IPointingAltAz:
31
36
  if isinstance(obj, Proxy):
32
- state: AltAzState | None = obj.get_state(IPointingAltAz)
37
+ state: AltAzState | None = obj.get_state(IPointingAltAz, max_age=max_age)
33
38
  elif isinstance(obj, Module):
34
39
  state = obj.comm.get_own_state(IPointingAltAz)
35
40
  else:
@@ -39,7 +44,7 @@ async def get_coords(
39
44
  return state.alt, state.az
40
45
  elif mode == IPointingRaDec:
41
46
  if isinstance(obj, Proxy):
42
- state2: RaDecState | None = obj.get_state(IPointingRaDec)
47
+ state2: RaDecState | None = obj.get_state(IPointingRaDec, max_age=max_age)
43
48
  elif isinstance(obj, Module):
44
49
  state2 = obj.comm.get_own_state(IPointingRaDec)
45
50
  else:
@@ -80,6 +85,7 @@ class FollowMixin:
80
85
  interval: float = 10,
81
86
  tolerance: float = 1,
82
87
  only_follow_when_ready: bool = True,
88
+ follow_max_age: float | None = None,
83
89
  *args: Any,
84
90
  **kwargs: Any,
85
91
  ):
@@ -91,6 +97,11 @@ class FollowMixin:
91
97
  tolerance: Tolerance in degrees between both devices to trigger new movement.
92
98
  mode: Set to "altaz" to follow Alt/Az coordinates or "radec" to follow RA/Dec.
93
99
  only_follow_when_ready: Only follow if is_ready() is True.
100
+ follow_max_age: Treat the followed device's cached position as unavailable once
101
+ it's older than this many seconds -- guards against silently following a frozen
102
+ position if the followed device's own position-publish loop dies while its
103
+ connection stays up. Defaults to 3x interval (loose enough to tolerate a slow
104
+ tick, tight enough to notice a dead feed within a few position checks).
94
105
  """
95
106
 
96
107
  # store
@@ -99,6 +110,7 @@ class FollowMixin:
99
110
  self.__follow_tolerance = tolerance
100
111
  self.__follow_mode = mode
101
112
  self.__follow_only_when_ready = only_follow_when_ready
113
+ self.__follow_max_age = follow_max_age if follow_max_age is not None else interval * 3
102
114
 
103
115
  # store self for later
104
116
  this = self
@@ -154,7 +166,7 @@ class FollowMixin:
154
166
  else:
155
167
  continue
156
168
  async with module.proxy(this.__follow_device, this.__follow_mode) as proxy:
157
- xy_coords = await get_coords(proxy, this.__follow_mode)
169
+ xy_coords = await get_coords(proxy, this.__follow_mode, max_age=this.__follow_max_age)
158
170
  if xy_coords is None:
159
171
  continue
160
172
  other_coords = build_skycoord(xy_coords, this.__follow_mode)
@@ -99,10 +99,6 @@ class DummyAutoFocus(Module, IAutoFocus):
99
99
  await self.comm.send_event(FocusFoundEvent(self._best_focus, error))
100
100
  return AutoFocusResult(focus=self._best_focus, focus_err=error)
101
101
 
102
- async def is_running(self, **kwargs: Any) -> bool:
103
- """Whether a service is running."""
104
- return self._running
105
-
106
102
  async def abort(self, **kwargs: Any) -> None:
107
103
  """Abort current actions."""
108
104
  self._abort.set()
@@ -84,7 +84,7 @@ class FocusModel(Module, IFocusModel):
84
84
  focuser: str | None = None,
85
85
  weather: str | None = None,
86
86
  interval: int = 300,
87
- temperatures: dict[str, dict[str, float]] | None = None,
87
+ temperatures: dict[str, dict[str, str]] | None = None,
88
88
  model: str | None = None,
89
89
  coefficients: dict[str, float] | None = None,
90
90
  update: bool = False,
@@ -96,6 +96,7 @@ class FocusModel(Module, IFocusModel):
96
96
  filter_offsets: dict[str, float] | None = None,
97
97
  filter_wheel: str | None = None,
98
98
  auto_focus: str | list[str] | None = None,
99
+ temp_max_age: float | None = None,
99
100
  **kwargs: Any,
100
101
  ):
101
102
  """Initialize a focus model.
@@ -115,6 +116,9 @@ class FocusModel(Module, IFocusModel):
115
116
  filter_offsets: Offsets for different filters. If None, they are not modeled.
116
117
  filter_wheel: Name of filter wheel module to use for fetching filter before setting focus.
117
118
  auto_focus: Name or list of names of auto-focus modules to accept focus values from.
119
+ temp_max_age: Treat a temperature module's cached ITemperatures reading as unavailable
120
+ once it's older than this many seconds -- guards against silently feeding a frozen
121
+ reading (from a dead sensor module) into the focus model. Defaults to 2x interval.
118
122
  """
119
123
  Module.__init__(self, **kwargs)
120
124
 
@@ -130,7 +134,8 @@ class FocusModel(Module, IFocusModel):
130
134
  self._focuser = focuser
131
135
  self._weather = weather
132
136
  self._interval = interval
133
- self._temperatures: dict[str, dict[str, float]] = {} if temperatures is None else temperatures
137
+ self._temperatures: dict[str, dict[str, str]] = {} if temperatures is None else temperatures
138
+ self._temp_max_age = temp_max_age if temp_max_age is not None else float(interval) * 2
134
139
  self._focuser_ready = True
135
140
  self._coefficients = {} if coefficients is None else coefficients
136
141
  self._update_model = update
@@ -175,11 +180,16 @@ class FocusModel(Module, IFocusModel):
175
180
  if self._update_model:
176
181
  await self._calc_focus_model()
177
182
 
178
- # publish initial states
183
+ # publish initial state -- dependencies (e.g. the weather module) may not be reachable
184
+ # yet at this point in startup, so fall back to a placeholder rather than leaving
185
+ # IFocusModel's state unpublished entirely; _update() overwrites it with a real
186
+ # measurement once dependencies are reachable
179
187
  try:
180
- await self.comm.set_state(IFocusModel, OptimalFocusState(focus=await self._get_optimal_focus()))
181
- except ValueError as e:
182
- log.warning("Could not publish initial focus model state: %s", e)
188
+ focus = await self._get_optimal_focus()
189
+ except (ValueError, exc.FocusError) as e:
190
+ log.warning("Could not compute initial focus model state, publishing placeholder instead: %s", e)
191
+ focus = 0.0
192
+ await self.comm.set_state(IFocusModel, OptimalFocusState(focus=focus))
183
193
 
184
194
  async def _update(self) -> None:
185
195
  # wait a little
@@ -318,7 +328,7 @@ class FocusModel(Module, IFocusModel):
318
328
  # get temperatures
319
329
  async with self.proxy(cfg["module"], ITemperatures) as proxy:
320
330
  try:
321
- temp_state = await proxy.wait_for_state(ITemperatures)
331
+ temp_state = await proxy.wait_for_state(ITemperatures, max_age=self._temp_max_age)
322
332
  except TimeoutError:
323
333
  raise FocusTimeoutError(f"Timeout waiting for temperatures from module {cfg['module']}.")
324
334
  module_temps[cfg["module"]] = (
@@ -291,10 +291,6 @@ class AutoFocusSeries(Module, CameraSettingsMixin, IAutoFocus):
291
291
  """Abort current actions."""
292
292
  self._abort.set()
293
293
 
294
- async def is_running(self, **kwargs: Any) -> bool:
295
- """Whether a service is running."""
296
- return self._running
297
-
298
294
  async def _on_bad_weather(self, event: Event, sender: str) -> bool:
299
295
  """Abort series if a bad weather event occurs.
300
296
 
@@ -95,14 +95,6 @@ class BaseGuiding(BasePointing, IAutoGuiding, IFitsHeaderBefore, IFitsHeaderAfte
95
95
  await self._reset_guiding(enabled=False)
96
96
  await self.comm.set_state(IRunning, RunningState(running=False))
97
97
 
98
- async def is_running(self, **kwargs: Any) -> bool:
99
- """Whether auto-guiding is running.
100
-
101
- Returns:
102
- Auto-guiding is running.
103
- """
104
- return self._enabled
105
-
106
98
  async def get_fits_header_before(
107
99
  self, namespaces: list[str] | None = None, **kwargs: Any
108
100
  ) -> dict[str, FitsHeaderEntry]:
@@ -103,10 +103,6 @@ class Acquisition(BasePointing, CameraSettingsMixin, IAcquisition):
103
103
  await self.comm.set_state(IAcquisition, AcquisitionState())
104
104
  await self.comm.set_state(IRunning, RunningState(running=False))
105
105
 
106
- async def is_running(self, **kwargs: Any) -> bool:
107
- """Whether a service is running."""
108
- return self._is_running
109
-
110
106
  @raises(exc.AbortedError, exc.AcquisitionError)
111
107
  @timeout(120)
112
108
  async def acquire_target(self, **kwargs: Any) -> AcquisitionResult:
@@ -59,10 +59,6 @@ class DummyAcquisition(Module, IAcquisition):
59
59
  await self.comm.set_state(IAcquisition, AcquisitionState())
60
60
  await self.comm.set_state(IRunning, RunningState(running=False))
61
61
 
62
- async def is_running(self, **kwargs: Any) -> bool:
63
- """Whether a service is running."""
64
- return self._is_running
65
-
66
62
  @timeout(120)
67
63
  async def acquire_target(self, **kwargs: Any) -> AcquisitionResult:
68
64
  """Acquire target at given coordinates.
@@ -56,9 +56,6 @@ class DummyAutoGuiding(Module, IAutoGuiding):
56
56
  await self.comm.set_state(IRunning, RunningState(running=False))
57
57
  await self._publish_guiding_state(loop_closed=False)
58
58
 
59
- async def is_running(self, **kwargs: Any) -> bool:
60
- return self._running
61
-
62
59
  async def _publish_guiding_state(self, loop_closed: bool) -> None:
63
60
  await self.comm.set_state(
64
61
  IAutoGuiding,
@@ -90,10 +90,6 @@ class Mastermind(Module, IAutonomous, IFitsHeaderBefore):
90
90
  self._running = False
91
91
  await self.comm.set_state(IRunning, RunningState(running=self._running))
92
92
 
93
- async def is_running(self, **kwargs: Any) -> bool:
94
- """Whether a service is running."""
95
- return self._running
96
-
97
93
  async def _run_thread(self) -> None:
98
94
  # wait a little
99
95
  await asyncio.sleep(5)
@@ -50,7 +50,7 @@ class PointingSeries(Module, IAutonomous):
50
50
  async def open(self) -> None:
51
51
  """Open module."""
52
52
  await Module.open(self)
53
- await self.comm.set_state(IRunning, RunningState(running=await self.is_running()))
53
+ await self.comm.set_state(IRunning, RunningState(running=True))
54
54
 
55
55
  async def start(self, **kwargs: Any) -> None:
56
56
  """Starts a service."""
@@ -60,10 +60,6 @@ class PointingSeries(Module, IAutonomous):
60
60
  """Stops a service."""
61
61
  pass
62
62
 
63
- async def is_running(self, **kwargs: Any) -> bool:
64
- """Whether a service is running."""
65
- return True
66
-
67
63
  async def _run_thread(self) -> None:
68
64
  """Run a pointing series."""
69
65
 
@@ -119,10 +119,6 @@ class Scheduler(Module, IStartStop, IRunnable):
119
119
  self._running = False
120
120
  await self.comm.set_state(IRunning, RunningState(running=self._running))
121
121
 
122
- async def is_running(self, **kwargs: Any) -> bool:
123
- """Whether scheduler is running."""
124
- return self._running
125
-
126
122
  async def _update_schedule(self) -> None:
127
123
  # get schedulable tasks and sort them
128
124
  log.info("Found update in schedulable block, downloading them...")
@@ -109,10 +109,6 @@ class Kiosk(Module, IStartStop):
109
109
  self._running = False
110
110
  await self.comm.set_state(IRunning, RunningState(running=self._running))
111
111
 
112
- async def is_running(self, **kwargs: Any) -> bool:
113
- """Whether kiosk mode is running."""
114
- return self._running
115
-
116
112
  async def _camera_thread(self) -> None:
117
113
  """Thread for taking images."""
118
114
 
@@ -63,10 +63,6 @@ class Trigger(Module, IAutonomous):
63
63
  self._running = False
64
64
  await self.comm.set_state(IRunning, RunningState(running=self._running))
65
65
 
66
- async def is_running(self, **kwargs: Any) -> bool:
67
- """Whether a service is running."""
68
- return self._running
69
-
70
66
  async def _handle_event(self, event: Event, sender: str) -> bool:
71
67
  """Handle an incoming event.
72
68
 
@@ -70,10 +70,6 @@ class MockWeather(Module, IWeather, IFitsHeaderBefore):
70
70
  self._active = False
71
71
  await self._publish_state()
72
72
 
73
- async def is_running(self, **kwargs: Any) -> bool:
74
- """Whether a service is running."""
75
- return self._active
76
-
77
73
  async def set_good(self, good: bool) -> None:
78
74
  """Set the simulated weather-good state, for use in tests and simulations.
79
75
 
@@ -112,10 +112,6 @@ class Weather(Module, IWeather, IFitsHeaderBefore):
112
112
  self._active = False
113
113
  await self.comm.set_state(IRunning, RunningState(running=self._active))
114
114
 
115
- async def is_running(self, **kwargs: Any) -> bool:
116
- """Whether a service is running."""
117
- return self._active
118
-
119
115
  async def _run(self) -> None:
120
116
  while True:
121
117
  await self._loop()
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pyobs-core"
3
- version = "2.0.0.dev43"
3
+ version = "2.0.0.dev45"
4
4
  description = "robotic telescope software"
5
5
  authors = [{ name = "Tim-Oliver Husser", email = "thusser@uni-goettingen.de" }]
6
6
  requires-python = ">=3.11"