pyobs-core 2.0.0.dev60__tar.gz → 2.0.0.dev62__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 (446) hide show
  1. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/PKG-INFO +1 -1
  2. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/mixins/fitsheader.py +11 -3
  3. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/utils/httpfilecache.py +47 -3
  4. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/backend/observationarchive.py +9 -3
  5. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/backend/taskarchive.py +5 -5
  6. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/http.py +16 -0
  7. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/vfs/httpfile.py +7 -9
  8. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyproject.toml +1 -1
  9. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/.gitignore +0 -0
  10. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/LICENSE +0 -0
  11. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/__init__.py +0 -0
  12. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/application.py +0 -0
  13. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/background_task.py +0 -0
  14. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/cli/__init__.py +0 -0
  15. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/cli/_cli.py +0 -0
  16. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/cli/pyobs.py +0 -0
  17. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/cli/pyobsd.py +0 -0
  18. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/cli/pyobsw.py +0 -0
  19. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/comm/__init__.py +0 -0
  20. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/comm/comm.py +0 -0
  21. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/comm/commlogging.py +0 -0
  22. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/comm/dummy/__init__.py +0 -0
  23. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/comm/dummy/dummycomm.py +0 -0
  24. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/comm/local/__init__.py +0 -0
  25. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/comm/local/localcomm.py +0 -0
  26. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/comm/local/localnetwork.py +0 -0
  27. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/comm/proxy.py +0 -0
  28. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/comm/xmpp/__init__.py +0 -0
  29. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/comm/xmpp/rpc.py +0 -0
  30. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/comm/xmpp/serializer.py +0 -0
  31. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/comm/xmpp/xep_0009/__init__.py +0 -0
  32. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/comm/xmpp/xep_0009/binding.py +0 -0
  33. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/comm/xmpp/xep_0009/rpc.py +0 -0
  34. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/comm/xmpp/xep_0009_timeout/__init__.py +0 -0
  35. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/comm/xmpp/xep_0009_timeout/rpc.py +0 -0
  36. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/comm/xmpp/xep_0009_timeout/stanza/RPC.py +0 -0
  37. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/comm/xmpp/xep_0009_timeout/stanza/__init__.py +0 -0
  38. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/comm/xmpp/xmppclient.py +0 -0
  39. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/comm/xmpp/xmppcomm.py +0 -0
  40. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/events/__init__.py +0 -0
  41. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/events/badweather.py +0 -0
  42. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/events/event.py +0 -0
  43. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/events/exposurestatuschanged.py +0 -0
  44. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/events/filterchanged.py +0 -0
  45. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/events/focusfound.py +0 -0
  46. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/events/goodweather.py +0 -0
  47. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/events/log.py +0 -0
  48. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/events/modechanged.py +0 -0
  49. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/events/moduleclosed.py +0 -0
  50. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/events/moduleopened.py +0 -0
  51. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/events/motionstatuschanged.py +0 -0
  52. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/events/move.py +0 -0
  53. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/events/newimage.py +0 -0
  54. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/events/newspectrum.py +0 -0
  55. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/events/offsets.py +0 -0
  56. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/events/roofclosing.py +0 -0
  57. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/events/roofopened.py +0 -0
  58. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/events/taskfailed.py +0 -0
  59. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/events/taskfinished.py +0 -0
  60. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/events/taskstarted.py +0 -0
  61. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/events/testevent.py +0 -0
  62. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/__init__.py +0 -0
  63. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/image.py +0 -0
  64. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/meta/__init__.py +0 -0
  65. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/meta/altazoffsets.py +0 -0
  66. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/meta/exptime.py +0 -0
  67. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/meta/genericoffset.py +0 -0
  68. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/meta/onskydistance.py +0 -0
  69. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/meta/pixeloffsets.py +0 -0
  70. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/meta/radecoffsets.py +0 -0
  71. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/meta/skyoffsets.py +0 -0
  72. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processor.py +0 -0
  73. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/__init__.py +0 -0
  74. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/_daobackgroundremover.py +0 -0
  75. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/annotation/__init__.py +0 -0
  76. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/annotation/_pillow.py +0 -0
  77. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/annotation/circle.py +0 -0
  78. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/annotation/crosshair.py +0 -0
  79. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/annotation/text.py +0 -0
  80. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/astrometry/__init__.py +0 -0
  81. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/astrometry/_dotnet_request.py +0 -0
  82. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/astrometry/_dotnet_request_builder.py +0 -0
  83. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/astrometry/_dotnet_request_logger.py +0 -0
  84. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/astrometry/_dotnet_response_saver.py +0 -0
  85. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/astrometry/astrometry.py +0 -0
  86. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/astrometry/dotnet.py +0 -0
  87. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/calibration/__init__.py +0 -0
  88. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/calibration/_calibration_cache.py +0 -0
  89. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/calibration/_ccddata_calibrator.py +0 -0
  90. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/calibration/calibration.py +0 -0
  91. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/detection/__init__.py +0 -0
  92. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/detection/_pysep_stats_calculator.py +0 -0
  93. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/detection/_source_catalog.py +0 -0
  94. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/detection/daophot.py +0 -0
  95. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/detection/pysep.py +0 -0
  96. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/detection/simpledisk.py +0 -0
  97. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/detection/sourcedetection.py +0 -0
  98. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/exptime/__init__.py +0 -0
  99. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/exptime/exptime.py +0 -0
  100. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/exptime/star.py +0 -0
  101. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/image/__init__.py +0 -0
  102. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/image/addfitsheaders.py +0 -0
  103. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/image/download.py +0 -0
  104. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/image/flip.py +0 -0
  105. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/image/grayscale.py +0 -0
  106. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/image/httpserver.py +0 -0
  107. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/image/normalize.py +0 -0
  108. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/image/save.py +0 -0
  109. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/image/saveimage.py +0 -0
  110. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/image/smooth.py +0 -0
  111. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/image/softbin.py +0 -0
  112. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/misc/__init__.py +0 -0
  113. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/misc/addmask.py +0 -0
  114. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/misc/catalogcircularmask.py +0 -0
  115. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/misc/circularmask.py +0 -0
  116. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/misc/createfilename.py +0 -0
  117. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/misc/imagesourcefilter.py +0 -0
  118. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/misc/removebackground.py +0 -0
  119. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/modules/__init__.py +0 -0
  120. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/modules/getfitsheaders.py +0 -0
  121. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/offsets/__init__.py +0 -0
  122. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/offsets/astrometry.py +0 -0
  123. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/offsets/brighteststar.py +0 -0
  124. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/offsets/brighteststar_guiding.py +0 -0
  125. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/offsets/dummyoffsets.py +0 -0
  126. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/offsets/dummyskyoffsets.py +0 -0
  127. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/offsets/fitsheader.py +0 -0
  128. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/offsets/offsets.py +0 -0
  129. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/offsets/pixeloffsets.py +0 -0
  130. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/offsets/projected.py +0 -0
  131. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/offsets/spilled_light.py +0 -0
  132. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/photometry/__init__.py +0 -0
  133. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/photometry/_photometry_calculator.py +0 -0
  134. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/photometry/_photutil_aperture_photometry.py +0 -0
  135. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/photometry/_sep_aperture_photometry.py +0 -0
  136. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/photometry/aperture_photometry.py +0 -0
  137. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/photometry/photometry.py +0 -0
  138. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/photometry/photutil.py +0 -0
  139. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/photometry/pysep.py +0 -0
  140. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/wcs/__init__.py +0 -0
  141. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/images/processors/wcs/solarhelioprojective.py +0 -0
  142. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IAbortable.py +0 -0
  143. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IAcquisition.py +0 -0
  144. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IAutoFocus.py +0 -0
  145. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IAutoGuiding.py +0 -0
  146. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IAutonomous.py +0 -0
  147. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IBinning.py +0 -0
  148. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/ICalibrate.py +0 -0
  149. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/ICamera.py +0 -0
  150. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IConfig.py +0 -0
  151. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/ICooling.py +0 -0
  152. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IData.py +0 -0
  153. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IDataSequence.py +0 -0
  154. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IDome.py +0 -0
  155. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IExposure.py +0 -0
  156. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IExposureTime.py +0 -0
  157. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IFilters.py +0 -0
  158. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IFitsHeaderAfter.py +0 -0
  159. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IFitsHeaderBefore.py +0 -0
  160. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IFlatField.py +0 -0
  161. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IFocusModel.py +0 -0
  162. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IFocuser.py +0 -0
  163. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IGain.py +0 -0
  164. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IImageFormat.py +0 -0
  165. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IImageType.py +0 -0
  166. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IMode.py +0 -0
  167. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IModule.py +0 -0
  168. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IMotion.py +0 -0
  169. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IMultiFiber.py +0 -0
  170. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IOffsetsAltAz.py +0 -0
  171. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IOffsetsRaDec.py +0 -0
  172. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IPointingAltAz.py +0 -0
  173. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IPointingBody.py +0 -0
  174. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IPointingHeliocentricPolar.py +0 -0
  175. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IPointingHeliographicStonyhurst.py +0 -0
  176. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IPointingHelioprojective.py +0 -0
  177. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IPointingOrbitalElements.py +0 -0
  178. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IPointingRaDec.py +0 -0
  179. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IPointingSeries.py +0 -0
  180. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IReady.py +0 -0
  181. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IRoof.py +0 -0
  182. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IRotation.py +0 -0
  183. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IRunnable.py +0 -0
  184. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IRunning.py +0 -0
  185. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IScriptRunner.py +0 -0
  186. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/ISpectrograph.py +0 -0
  187. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IStartStop.py +0 -0
  188. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IStructuredConfig.py +0 -0
  189. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/ISyncTarget.py +0 -0
  190. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/ITelescope.py +0 -0
  191. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/ITemperatures.py +0 -0
  192. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/ITrackingMode.py +0 -0
  193. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/ITrackingRate.py +0 -0
  194. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IVideo.py +0 -0
  195. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IWeather.py +0 -0
  196. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/IWindow.py +0 -0
  197. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/__init__.py +0 -0
  198. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/interfaces/interface.py +0 -0
  199. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/mixins/__init__.py +0 -0
  200. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/mixins/camerasettings.py +0 -0
  201. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/mixins/fitsnamespace.py +0 -0
  202. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/mixins/follow.py +0 -0
  203. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/mixins/motionstatus.py +0 -0
  204. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/mixins/pipeline.py +0 -0
  205. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/mixins/waitformotion.py +0 -0
  206. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/mixins/weatheraware.py +0 -0
  207. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/__init__.py +0 -0
  208. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/camera/__init__.py +0 -0
  209. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/camera/adaptive.py +0 -0
  210. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/camera/basecamera.py +0 -0
  211. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/camera/basespectrograph.py +0 -0
  212. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/camera/basevideo.py +0 -0
  213. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/camera/dummycamera.py +0 -0
  214. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/camera/dummyspectrograph.py +0 -0
  215. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/camera/dummyvideo.py +0 -0
  216. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/camera/pipelinecamera.py +0 -0
  217. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/flatfield/__init__.py +0 -0
  218. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/flatfield/flatfield.py +0 -0
  219. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/flatfield/pointing.py +0 -0
  220. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/flatfield/scheduler.py +0 -0
  221. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/focus/__init__.py +0 -0
  222. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/focus/dummyautofocus.py +0 -0
  223. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/focus/focusmodel.py +0 -0
  224. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/focus/focusseries.py +0 -0
  225. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/image/__init__.py +0 -0
  226. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/image/imagewatcher.py +0 -0
  227. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/image/imagewriter.py +0 -0
  228. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/image/pipeline.py +0 -0
  229. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/image/seeing.py +0 -0
  230. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/module.py +0 -0
  231. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/pointing/__init__.py +0 -0
  232. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/pointing/_base.py +0 -0
  233. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/pointing/_baseguiding.py +0 -0
  234. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/pointing/acquisition.py +0 -0
  235. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/pointing/autoguiding.py +0 -0
  236. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/pointing/dummyacquisition.py +0 -0
  237. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/pointing/dummyguiding.py +0 -0
  238. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/pointing/guidingstatistics/__init__.py +0 -0
  239. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/pointing/guidingstatistics/guidingstatistics.py +0 -0
  240. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/pointing/guidingstatistics/pixeloffset.py +0 -0
  241. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/pointing/guidingstatistics/skyoffsets.py +0 -0
  242. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/pointing/guidingstatistics/uptime.py +0 -0
  243. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/pointing/scienceframeguiding.py +0 -0
  244. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/robotic/__init__.py +0 -0
  245. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/robotic/mastermind.py +0 -0
  246. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/robotic/pointing.py +0 -0
  247. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/robotic/scheduler.py +0 -0
  248. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/robotic/scriptrunner.py +0 -0
  249. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/roof/__init__.py +0 -0
  250. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/roof/basedome.py +0 -0
  251. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/roof/baseroof.py +0 -0
  252. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/roof/dummyroof.py +0 -0
  253. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/telescope/__init__.py +0 -0
  254. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/telescope/_dummytelescopebase.py +0 -0
  255. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/telescope/basetelescope.py +0 -0
  256. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/telescope/dummyaltaztelescope.py +0 -0
  257. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/telescope/dummyradectelescope.py +0 -0
  258. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/telescope/dummysolartelescope.py +0 -0
  259. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/test/__init__.py +0 -0
  260. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/test/standalone.py +0 -0
  261. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/utils/__init__.py +0 -0
  262. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/utils/dummymode.py +0 -0
  263. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/utils/fluentlogger.py +0 -0
  264. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/utils/kiosk.py +0 -0
  265. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/utils/matrix.py +0 -0
  266. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/utils/stellarium.py +0 -0
  267. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/utils/telegram.py +0 -0
  268. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/utils/trigger.py +0 -0
  269. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/weather/__init__.py +0 -0
  270. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/weather/mockweather.py +0 -0
  271. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/weather/weather.py +0 -0
  272. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/weather/weather_api.py +0 -0
  273. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/modules/weather/weather_state.py +0 -0
  274. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/object.py +0 -0
  275. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/py.typed +0 -0
  276. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/__init__.py +0 -0
  277. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/observation.py +0 -0
  278. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/__init__.py +0 -0
  279. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/_executor.py +0 -0
  280. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/astroplanscheduler.py +0 -0
  281. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/constraints/__init__.py +0 -0
  282. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/constraints/airmassconstraint.py +0 -0
  283. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/constraints/constraint.py +0 -0
  284. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/constraints/moonilluminationconstraint.py +0 -0
  285. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/constraints/moonseparationconstraint.py +0 -0
  286. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/constraints/solarelevationconstraint.py +0 -0
  287. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/constraints/timeconstraint.py +0 -0
  288. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/dataprovider.py +0 -0
  289. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/merits/__init__.py +0 -0
  290. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/merits/aftertime.py +0 -0
  291. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/merits/beforetime.py +0 -0
  292. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/merits/constant.py +0 -0
  293. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/merits/follow.py +0 -0
  294. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/merits/interval.py +0 -0
  295. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/merits/merit.py +0 -0
  296. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/merits/pernight.py +0 -0
  297. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/merits/random.py +0 -0
  298. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/merits/timewindow.py +0 -0
  299. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/merits/transit.py +0 -0
  300. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/observationarchiveevolution.py +0 -0
  301. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/ondemandscheduler.py +0 -0
  302. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/targets/__init__.py +0 -0
  303. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/targets/dynamictarget.py +0 -0
  304. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/targets/heliocentricpolartarget.py +0 -0
  305. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/targets/helioprojectivetarget.py +0 -0
  306. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/targets/picker/__init__.py +0 -0
  307. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/targets/picker/csvpicker.py +0 -0
  308. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/targets/picker/picker.py +0 -0
  309. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/targets/siderealtarget.py +0 -0
  310. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/targets/target.py +0 -0
  311. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scheduler/taskscheduler.py +0 -0
  312. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scripts/__init__.py +0 -0
  313. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scripts/calibration/__init__.py +0 -0
  314. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scripts/calibration/darkbias.py +0 -0
  315. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scripts/calibration/pointing.py +0 -0
  316. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scripts/calibration/skyflats.py +0 -0
  317. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scripts/control/__init__.py +0 -0
  318. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scripts/control/cases.py +0 -0
  319. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scripts/control/conditional.py +0 -0
  320. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scripts/control/parallel.py +0 -0
  321. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scripts/control/selector.py +0 -0
  322. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scripts/control/sequential.py +0 -0
  323. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scripts/exceptions.py +0 -0
  324. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scripts/imaging/__init__.py +0 -0
  325. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scripts/imaging/autofocus.py +0 -0
  326. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scripts/imaging/imaging.py +0 -0
  327. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scripts/imaging/transitimaging.py +0 -0
  328. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scripts/script.py +0 -0
  329. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scripts/utils/__init__.py +0 -0
  330. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scripts/utils/callmodule.py +0 -0
  331. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scripts/utils/debugtrigger.py +0 -0
  332. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/scripts/utils/log.py +0 -0
  333. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/__init__.py +0 -0
  334. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/backend/__init__.py +0 -0
  335. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/filesystem/__init__.py +0 -0
  336. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/filesystem/observationarchive.py +0 -0
  337. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/filesystem/taskarchive.py +0 -0
  338. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/lco/__init__.py +0 -0
  339. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/lco/_portal.py +0 -0
  340. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/lco/_schedulereader.py +0 -0
  341. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/lco/_schedulewriter.py +0 -0
  342. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/lco/configdb.py +0 -0
  343. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/lco/mockobservationarchive.py +0 -0
  344. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/lco/observationarchive.py +0 -0
  345. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/lco/scripts/__init__.py +0 -0
  346. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/lco/scripts/autofocus.py +0 -0
  347. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/lco/scripts/default.py +0 -0
  348. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/lco/scripts/script.py +0 -0
  349. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/lco/task.py +0 -0
  350. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/lco/taskarchive.py +0 -0
  351. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/lco/taskrunner.py +0 -0
  352. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/memory/__init__.py +0 -0
  353. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/memory/observationarchive.py +0 -0
  354. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/memory/taskarchive.py +0 -0
  355. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/observationarchive.py +0 -0
  356. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/storage/taskarchive.py +0 -0
  357. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/task.py +0 -0
  358. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/taskrunner.py +0 -0
  359. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/utils/__init__.py +0 -0
  360. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/utils/archive/__init__.py +0 -0
  361. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/utils/archive/archive.py +0 -0
  362. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/utils/archive/local_archive.py +0 -0
  363. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/utils/archive/pyobs_archive.py +0 -0
  364. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/utils/exptime/__init__.py +0 -0
  365. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/utils/exptime/exptime.py +0 -0
  366. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/utils/exptime/stellarexptime.py +0 -0
  367. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/utils/skyflats/__init__.py +0 -0
  368. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/utils/skyflats/exptimeeval.py +0 -0
  369. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/utils/skyflats/flatfielder.py +0 -0
  370. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/utils/skyflats/pointing/__init__.py +0 -0
  371. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/utils/skyflats/pointing/base.py +0 -0
  372. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/utils/skyflats/pointing/static.py +0 -0
  373. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/utils/skyflats/priorities/__init__.py +0 -0
  374. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/utils/skyflats/priorities/archive.py +0 -0
  375. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/utils/skyflats/priorities/base.py +0 -0
  376. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/utils/skyflats/priorities/const.py +0 -0
  377. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/robotic/utils/skyflats/scheduler.py +0 -0
  378. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/__init__.py +0 -0
  379. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/average.py +0 -0
  380. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/cache.py +0 -0
  381. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/config.py +0 -0
  382. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/config_schema.py +0 -0
  383. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/coordinates.py +0 -0
  384. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/curvefit.py +0 -0
  385. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/enums.py +0 -0
  386. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/exceptions.py +0 -0
  387. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/fits.py +0 -0
  388. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/focusseries/__init__.py +0 -0
  389. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/focusseries/base.py +0 -0
  390. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/focusseries/photometry.py +0 -0
  391. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/focusseries/projection.py +0 -0
  392. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/grids/__init__.py +0 -0
  393. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/grids/filters.py +0 -0
  394. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/grids/grid.py +0 -0
  395. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/grids/gridnode.py +0 -0
  396. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/grids/pipeline.py +0 -0
  397. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/gui/__init__.py +0 -0
  398. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/gui/camera/__init__.py +0 -0
  399. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/gui/camera/binningwidget.py +0 -0
  400. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/gui/camera/datadisplaywidget.py +0 -0
  401. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/gui/camera/exposewidget.py +0 -0
  402. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/gui/camera/exposuretimewidget.py +0 -0
  403. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/gui/camera/imageformatwidget.py +0 -0
  404. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/gui/camera/listpickerdialog.py +0 -0
  405. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/gui/camera/windowingwidget.py +0 -0
  406. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/influxdb.py +0 -0
  407. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/logger.py +0 -0
  408. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/logging/__init__.py +0 -0
  409. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/logging/context.py +0 -0
  410. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/logging/resolvableerror.py +0 -0
  411. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/modulegui.py +0 -0
  412. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/offsets/__init__.py +0 -0
  413. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/offsets/applyaltazoffsets.py +0 -0
  414. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/offsets/applyoffsets.py +0 -0
  415. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/offsets/applyradecoffsets.py +0 -0
  416. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/parallel.py +0 -0
  417. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/pipeline/__init__.py +0 -0
  418. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/pipeline/night.py +0 -0
  419. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/pipeline/pipeline.py +0 -0
  420. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/publisher/__init__.py +0 -0
  421. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/publisher/csv.py +0 -0
  422. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/publisher/http.py +0 -0
  423. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/publisher/log.py +0 -0
  424. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/publisher/multi.py +0 -0
  425. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/publisher/publisher.py +0 -0
  426. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/serialization.py +0 -0
  427. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/shellcommand.py +0 -0
  428. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/threads/__init__.py +0 -0
  429. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/threads/lockwithabort.py +0 -0
  430. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/time.py +0 -0
  431. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/utils/units.py +0 -0
  432. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/version.py +0 -0
  433. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/vfs/__init__.py +0 -0
  434. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/vfs/archivefile.py +0 -0
  435. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/vfs/bufferedfile.py +0 -0
  436. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/vfs/file.py +0 -0
  437. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/vfs/filelists/__init__.py +0 -0
  438. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/vfs/filelists/filelist.py +0 -0
  439. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/vfs/filelists/testing.py +0 -0
  440. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/vfs/localfile.py +0 -0
  441. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/vfs/memfile.py +0 -0
  442. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/vfs/sftpfile.py +0 -0
  443. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/vfs/smbfile.py +0 -0
  444. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/vfs/sshfile.py +0 -0
  445. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/pyobs/vfs/tempfile.py +0 -0
  446. {pyobs_core-2.0.0.dev60 → pyobs_core-2.0.0.dev62}/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.dev60
3
+ Version: 2.0.0.dev62
4
4
  Summary: robotic telescope software
5
5
  Author-email: Tim-Oliver Husser <thusser@uni-goettingen.de>
6
6
  License-Expression: MIT
@@ -277,6 +277,11 @@ class ImageFitsHeaderMixin(FitsHeaderMixin):
277
277
  self._fitsheadermixin_centre = centre
278
278
  self._fitsheadermixin_rotation = rotation
279
279
 
280
+ # only warn once per missing-header case, since these repeat on every single frame
281
+ self._fitsheadermixin_warned_cdelt = False
282
+ self._fitsheadermixin_warned_crpix = False
283
+ self._fitsheadermixin_warned_cd_matrix = False
284
+
280
285
  @property
281
286
  def rotation(self) -> float | None:
282
287
  return self._fitsheadermixin_rotation
@@ -322,8 +327,9 @@ class ImageFitsHeaderMixin(FitsHeaderMixin):
322
327
  hdr["CUNIT1"] = ("deg", "Units of CRVAL1, CDELT1")
323
328
  hdr["CUNIT2"] = ("deg", "Units of CRVAL2, CDELT2")
324
329
  hdr["WCSAXES"] = (2, "Number of WCS axes")
325
- else:
330
+ elif not self._fitsheadermixin_warned_cdelt:
326
331
  log.warning("Could not calculate CDELT1/CDELT2 (DET-PIXL/TEL-FOCL/DET-BIN1/DET-BIN2 missing).")
332
+ self._fitsheadermixin_warned_cdelt = True
327
333
 
328
334
  # centre pixel
329
335
  if self._fitsheadermixin_centre is not None:
@@ -341,10 +347,11 @@ class ImageFitsHeaderMixin(FitsHeaderMixin):
341
347
  off_y = v("YORGSUBF") if "YORGSUBF" in hdr else 0.0
342
348
  hdr["CRPIX1"] = ((v("DET-CPX1") - off_x) / v("DET-BIN1"), "Reference x-pixel position in binned image")
343
349
  hdr["CRPIX2"] = ((v("DET-CPX2") - off_y) / v("DET-BIN2"), "Reference y-pixel position in binned image")
344
- else:
350
+ elif not self._fitsheadermixin_warned_crpix:
345
351
  log.warning(
346
352
  "Could not calculate CRPIX1/CRPIX2 " "(XORGSUBF/YORGSUBF/DET-CPX1/TEL-CPX2/DET-BIN1/DET-BIN2) missing."
347
353
  )
354
+ self._fitsheadermixin_warned_crpix = True
348
355
  # only add all this stuff for OBJECT images
349
356
  if "IMAGETYP" not in hdr or hdr["IMAGETYP"] not in ["dark", "bias"]:
350
357
  # projection, only override if not already set
@@ -368,8 +375,9 @@ class ImageFitsHeaderMixin(FitsHeaderMixin):
368
375
  hdr["PC1_2"] = (-sin_theta, "Partial of first axis coordinate w.r.t. y")
369
376
  hdr["PC2_1"] = (+sin_theta, "Partial of second axis coordinate w.r.t. x")
370
377
  hdr["PC2_2"] = (+cos_theta, "Partial of second axis coordinate w.r.t. y")
371
- else:
378
+ elif not self._fitsheadermixin_warned_cd_matrix:
372
379
  log.warning("Could not calculate CD matrix (rotation or CDELT1/CDELT2 missing.")
380
+ self._fitsheadermixin_warned_cd_matrix = True
373
381
 
374
382
 
375
383
  class SpectrumFitsHeaderMixin(FitsHeaderMixin):
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import hmac
3
4
  import logging
4
5
  from typing import Any
5
6
 
@@ -15,13 +16,22 @@ log = logging.getLogger(__name__)
15
16
  class HttpFileCache(Module):
16
17
  """A file cache based on a HTTP server."""
17
18
 
18
- def __init__(self, port: int = 37075, cache_size: int = 25, max_file_size: int = 100, **kwargs: Any):
19
+ def __init__(
20
+ self,
21
+ port: int = 37075,
22
+ cache_size: int = 25,
23
+ max_file_size: int = 100,
24
+ token: str | None = None,
25
+ **kwargs: Any,
26
+ ):
19
27
  """Initializes file cache.
20
28
 
21
29
  Args:
22
30
  port: Port for HTTP server.
23
31
  cache_size: Size of file cache, i.e. number of files to cache.
24
32
  max_file_size: Maximum file size in MB.
33
+ token: Shared secret required in the "Authorization: Bearer <token>" header for
34
+ download/upload access. If None (default), no auth is enforced.
25
35
  """
26
36
  Module.__init__(self, **kwargs)
27
37
 
@@ -31,6 +41,7 @@ class HttpFileCache(Module):
31
41
  self._port = port
32
42
  self._cache_size = cache_size
33
43
  self._max_file_size = max_file_size * 1024 * 1024
44
+ self._token = token
34
45
 
35
46
  # define web server
36
47
  self._app = web.Application(client_max_size=self._max_file_size)
@@ -38,6 +49,7 @@ class HttpFileCache(Module):
38
49
  [
39
50
  web.get("/ping", self.ping_handler),
40
51
  web.get("/{filename}", self.download_handler),
52
+ web.options("/{filename}", self.options_handler),
41
53
  web.post("/", self.upload_handler),
42
54
  ]
43
55
  )
@@ -67,6 +79,19 @@ class HttpFileCache(Module):
67
79
  """Whether the server is started."""
68
80
  return self._is_listening
69
81
 
82
+ def _check_auth(self, request: web.Request) -> None:
83
+ """Raises HTTPUnauthorized if a token is configured and the request doesn't carry it.
84
+
85
+ Args:
86
+ request: Request to check.
87
+ """
88
+ if self._token is None:
89
+ return
90
+ prefix = "Bearer "
91
+ header = request.headers.get("Authorization", "")
92
+ if not header.startswith(prefix) or not hmac.compare_digest(header[len(prefix) :], self._token):
93
+ raise web.HTTPUnauthorized()
94
+
70
95
  async def ping_handler(self, request: web.Request) -> web.Response:
71
96
  """Handles GET access to /ping for testing connectivity.
72
97
 
@@ -76,7 +101,24 @@ class HttpFileCache(Module):
76
101
  Returns:
77
102
  Response with a JSON status.
78
103
  """
79
- return web.json_response({"status": "ok"})
104
+ return web.json_response({"status": "ok"}, headers={"Access-Control-Allow-Origin": "*"})
105
+
106
+ async def options_handler(self, request: web.Request) -> web.Response:
107
+ """Handles OPTIONS access to /{filename} for CORS preflight requests.
108
+
109
+ Args:
110
+ request: Request to respond to.
111
+
112
+ Returns:
113
+ Empty response with CORS headers.
114
+ """
115
+ return web.Response(
116
+ headers={
117
+ "Access-Control-Allow-Origin": "*",
118
+ "Access-Control-Allow-Methods": "GET",
119
+ "Access-Control-Allow-Headers": "Authorization",
120
+ }
121
+ )
80
122
 
81
123
  async def download_handler(self, request: web.Request) -> web.Response:
82
124
  """Handles GET access to /{filename} and returns image.
@@ -87,6 +129,7 @@ class HttpFileCache(Module):
87
129
  Returns:
88
130
  Response containing image.
89
131
  """
132
+ self._check_auth(request)
90
133
 
91
134
  # get filename
92
135
  filename = request.match_info["filename"]
@@ -98,7 +141,7 @@ class HttpFileCache(Module):
98
141
 
99
142
  # send it
100
143
  log.info("Serving file %s.", filename)
101
- return web.Response(body=data)
144
+ return web.Response(body=data, headers={"Access-Control-Allow-Origin": "*"})
102
145
 
103
146
  async def upload_handler(self, request: web.Request) -> web.Response:
104
147
  """Handles PUSH access to /, stores image and returns filename.
@@ -109,6 +152,7 @@ class HttpFileCache(Module):
109
152
  Returns:
110
153
  Response containing filename.
111
154
  """
155
+ self._check_auth(request)
112
156
 
113
157
  # read multipart data
114
158
  reader = await request.multipart()
@@ -9,7 +9,7 @@ import aiohttp
9
9
 
10
10
  from pyobs.robotic import ObservationArchive, Task, TaskArchive
11
11
  from pyobs.robotic.observation import Observation, ObservationList, ObservationState
12
- from pyobs.utils.http import http_request_with_retries
12
+ from pyobs.utils.http import http_request_paginated, http_request_with_retries
13
13
  from pyobs.utils.time import Time
14
14
 
15
15
  log = logging.getLogger(__name__)
@@ -146,6 +146,9 @@ class BackendObservationArchive(ObservationArchive):
146
146
  if obs.state == "pending" and obs.start < time < obs.end:
147
147
  if task_archive is not None:
148
148
  await obs.fetch_task(task_archive)
149
+ if obs.task is None:
150
+ log.error("Could not resolve task for observation %s, skipping.", obs.id)
151
+ continue
149
152
  return obs
150
153
  else:
151
154
  return None
@@ -165,6 +168,9 @@ class BackendObservationArchive(ObservationArchive):
165
168
  if obs.state == "in_progress":
166
169
  if task_archive is not None:
167
170
  await obs.fetch_task(task_archive)
171
+ if obs.task is None:
172
+ log.error("Could not resolve task for observation %s, skipping.", obs.id)
173
+ continue
168
174
  return obs
169
175
  else:
170
176
  return None
@@ -223,8 +229,8 @@ class BackendObservationArchive(ObservationArchive):
223
229
  params["end_before"] = end_before.isot
224
230
  if end_after is not None:
225
231
  params["end_after"] = end_after.isot
226
- observations = await http_request_with_retries(self._session, url, params=params)
227
- return ObservationList([self.pyobs_model_validate(Observation, obs) for obs in observations["results"]])
232
+ observations = await http_request_paginated(self._session, url, params=params)
233
+ return ObservationList([self.pyobs_model_validate(Observation, obs) for obs in observations])
228
234
 
229
235
 
230
236
  __all__ = ["BackendObservationArchive"]
@@ -7,7 +7,7 @@ import aiohttp
7
7
 
8
8
  from pyobs.robotic.storage.taskarchive import TaskArchive
9
9
  from pyobs.robotic.task import Project, Task
10
- from pyobs.utils.http import http_request_with_retries
10
+ from pyobs.utils.http import http_request_paginated, http_request_with_retries
11
11
  from pyobs.utils.time import Time
12
12
 
13
13
  log = logging.getLogger(__name__)
@@ -75,13 +75,13 @@ class BackendTaskArchive(TaskArchive):
75
75
 
76
76
  async def _get_projects(self) -> list[Project]:
77
77
  """Fetch projects from backend."""
78
- projects = await http_request_with_retries(self._session, urljoin(self._url, "/api/projects/"))
79
- return [self.pyobs_model_validate(Project, project) for project in projects["results"]]
78
+ projects = await http_request_paginated(self._session, urljoin(self._url, "/api/projects/"))
79
+ return [self.pyobs_model_validate(Project, project) for project in projects]
80
80
 
81
81
  async def _get_tasks(self) -> list[Task]:
82
82
  """Fetch tasks from backend."""
83
- tasks = await http_request_with_retries(self._session, urljoin(self._url, "/api/tasks/"))
84
- return [self.pyobs_model_validate(Task, task) for task in tasks["results"]]
83
+ tasks = await http_request_paginated(self._session, urljoin(self._url, "/api/tasks/"))
84
+ return [self.pyobs_model_validate(Task, task) for task in tasks]
85
85
 
86
86
  async def last_changed(self) -> Time | None:
87
87
  """Returns time when last time any tasks changed."""
@@ -28,3 +28,19 @@ async def http_request_with_retries(
28
28
  if response.status != expected_status:
29
29
  raise RuntimeError(f"Invalid response from server: HTTP {response.status}")
30
30
  return cast(dict[str, Any], await response.json())
31
+
32
+
33
+ async def http_request_paginated(
34
+ session: aiohttp.ClientSession, url: str, method: str = "get", expected_status: int = 200, **kwargs: Any
35
+ ) -> list[dict[str, Any]]:
36
+ """Fetches all pages of a DRF-style paginated list endpoint and returns the combined results."""
37
+ results: list[dict[str, Any]] = []
38
+ next_url: str | None = url
39
+ while next_url is not None:
40
+ data = await http_request_with_retries(
41
+ session, next_url, method=method, expected_status=expected_status, **kwargs
42
+ )
43
+ results.extend(data["results"])
44
+ next_url = data.get("next")
45
+ kwargs = {}
46
+ return results
@@ -23,8 +23,7 @@ class HttpFile(BufferedFile):
23
23
  mode: str = "r",
24
24
  download: str | None = None,
25
25
  upload: str | None = None,
26
- username: str | None = None,
27
- password: str | None = None,
26
+ token: str | None = None,
28
27
  verify_tls: bool = False,
29
28
  timeout: int = 30,
30
29
  **kwargs: Any,
@@ -36,8 +35,7 @@ class HttpFile(BufferedFile):
36
35
  mode: Open mode (r/w).
37
36
  download: Base URL for downloading files. If None, no read access possible.
38
37
  upload: Base URL for uploading files. If None, no write access possible.
39
- username: Username for accessing the HTTP server.
40
- password: Password for accessing the HTTP server.
38
+ token: Shared secret sent as "Authorization: Bearer <token>" to the HTTP server.
41
39
  verify_tls: Whether to verify TLS certificates.
42
40
  timeout: Timeout in seconds for uploading/downloading files.
43
41
  """
@@ -49,9 +47,7 @@ class HttpFile(BufferedFile):
49
47
  self._timeout = aiohttp.ClientTimeout(total=timeout)
50
48
 
51
49
  # auth
52
- self._auth = None
53
- if username is not None and password is not None:
54
- self._auth = aiohttp.BasicAuth(username, password)
50
+ self._headers = {"Authorization": f"Bearer {token}"} if token is not None else {}
55
51
 
56
52
  # filename is not allowed to start with a / or contain ..
57
53
  if name.startswith("/") or ".." in name:
@@ -91,7 +87,7 @@ class HttpFile(BufferedFile):
91
87
 
92
88
  # do request
93
89
  async with aiohttp.ClientSession() as session:
94
- async with session.get(self.url, auth=self._auth, timeout=self._timeout) as response:
90
+ async with session.get(self.url, headers=self._headers, timeout=self._timeout) as response:
95
91
  # check response
96
92
  if response.status == 200:
97
93
  # get data and return it
@@ -165,7 +161,9 @@ class HttpFile(BufferedFile):
165
161
  async with aiohttp.ClientSession() as session:
166
162
  data = aiohttp.FormData()
167
163
  data.add_field("file", self._buffer(filename), filename=filename)
168
- async with session.post(self._upload_path, auth=self._auth, data=data, timeout=self._timeout) as response:
164
+ async with session.post(
165
+ self._upload_path, headers=self._headers, data=data, timeout=self._timeout
166
+ ) as response:
169
167
  if response.status == 401:
170
168
  log.error("Wrong credentials for uploading file.")
171
169
  raise FileNotFoundError
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pyobs-core"
3
- version = "2.0.0.dev60"
3
+ version = "2.0.0.dev62"
4
4
  description = "robotic telescope software"
5
5
  authors = [{ name = "Tim-Oliver Husser", email = "thusser@uni-goettingen.de" }]
6
6
  requires-python = ">=3.11"