arcsecond 4.3.2__tar.gz → 4.3.3__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 (121) hide show
  1. {arcsecond-4.3.2 → arcsecond-4.3.3}/PKG-INFO +1 -1
  2. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/api/endpoint.py +10 -1
  3. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/api/resources.py +1 -0
  4. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/targets.py +7 -8
  5. {arcsecond-4.3.2 → arcsecond-4.3.3}/pyproject.toml +1 -1
  6. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/api/test_config.py +16 -6
  7. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_hosting_database.py +13 -3
  8. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_targets_planning.py +5 -2
  9. {arcsecond-4.3.2 → arcsecond-4.3.3}/uv.lock +1 -1
  10. {arcsecond-4.3.2 → arcsecond-4.3.3}/.docker/Dockerfile_postgres +0 -0
  11. {arcsecond-4.3.2 → arcsecond-4.3.3}/.docker/Dockerfile_redis +0 -0
  12. {arcsecond-4.3.2 → arcsecond-4.3.3}/.flake8 +0 -0
  13. {arcsecond-4.3.2 → arcsecond-4.3.3}/.gitattributes +0 -0
  14. {arcsecond-4.3.2 → arcsecond-4.3.3}/.github/dependabot.yml +0 -0
  15. {arcsecond-4.3.2 → arcsecond-4.3.3}/.github/workflows/pythonpublish.yml +0 -0
  16. {arcsecond-4.3.2 → arcsecond-4.3.3}/.github/workflows/tests.yml +0 -0
  17. {arcsecond-4.3.2 → arcsecond-4.3.3}/.gitignore +0 -0
  18. {arcsecond-4.3.2 → arcsecond-4.3.3}/LICENSE +0 -0
  19. {arcsecond-4.3.2 → arcsecond-4.3.3}/Makefile +0 -0
  20. {arcsecond-4.3.2 → arcsecond-4.3.3}/README.md +0 -0
  21. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/__init__.py +0 -0
  22. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/__version__.py +0 -0
  23. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/alpaca/__init__.py +0 -0
  24. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/alpaca/commands.py +0 -0
  25. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/alpaca/dome_probe.py +0 -0
  26. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/alpaca/probe.py +0 -0
  27. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/alpaca/telescope_probe.py +0 -0
  28. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/api/__init__.py +0 -0
  29. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/api/config.py +0 -0
  30. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/api/constants.py +0 -0
  31. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/api/main.py +0 -0
  32. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/cli.py +0 -0
  33. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/cloud/__init__.py +0 -0
  34. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/cloud/auth.py +0 -0
  35. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/cloud/resources.py +0 -0
  36. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/cloud/uploader/__init__.py +0 -0
  37. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/cloud/uploader/constants.py +0 -0
  38. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/cloud/uploader/context.py +0 -0
  39. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/cloud/uploader/datafiles/__init__.py +0 -0
  40. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/cloud/uploader/datafiles/context.py +0 -0
  41. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/cloud/uploader/datafiles/errors.py +0 -0
  42. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/cloud/uploader/datafiles/uploader.py +0 -0
  43. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/cloud/uploader/datafiles/utils.py +0 -0
  44. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/cloud/uploader/errors.py +0 -0
  45. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/cloud/uploader/logger.py +0 -0
  46. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/cloud/uploader/uploader.py +0 -0
  47. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/cloud/uploader/utils.py +0 -0
  48. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/cloud/uploader/walker.py +0 -0
  49. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/cloud/uploads.py +0 -0
  50. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/docgen.py +0 -0
  51. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/errors.py +0 -0
  52. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/hosting/__init__.py +0 -0
  53. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/hosting/backups.py +0 -0
  54. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/hosting/check.py +0 -0
  55. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/hosting/composedoc.py +0 -0
  56. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/hosting/database.py +0 -0
  57. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/hosting/docker/__init__.py +0 -0
  58. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/hosting/docker/docker-compose.yml +0 -0
  59. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/hosting/lifecycle.py +0 -0
  60. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/hosting/local.py +0 -0
  61. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/hosting/stack.py +0 -0
  62. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/hosting/token.py +0 -0
  63. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/hosting/utils.py +0 -0
  64. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/imagesources/__init__.py +0 -0
  65. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/imagesources/autostart.py +0 -0
  66. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/imagesources/commands.py +0 -0
  67. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/imagesources/detection.py +0 -0
  68. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/imagesources/proxy.py +0 -0
  69. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/imagesources/registry.py +0 -0
  70. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/imagesources/runtime.py +0 -0
  71. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/imagesources/sources/__init__.py +0 -0
  72. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/imagesources/sources/base.py +0 -0
  73. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/imagesources/sources/filewatch.py +0 -0
  74. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/imagesources/sources/mdns.py +0 -0
  75. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/imagesources/sources/network.py +0 -0
  76. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/imagesources/sources/opencv.py +0 -0
  77. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/imagesources/store.py +0 -0
  78. {arcsecond-4.3.2 → arcsecond-4.3.3}/arcsecond/options.py +0 -0
  79. {arcsecond-4.3.2 → arcsecond-4.3.3}/examples/example_upload_files.py +0 -0
  80. {arcsecond-4.3.2 → arcsecond-4.3.3}/requirements.txt +0 -0
  81. {arcsecond-4.3.2 → arcsecond-4.3.3}/setup.cfg +0 -0
  82. {arcsecond-4.3.2 → arcsecond-4.3.3}/setup.py +0 -0
  83. {arcsecond-4.3.2 → arcsecond-4.3.3}/sonar-project.properties +0 -0
  84. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/__init__.py +0 -0
  85. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/api/__init__.py +0 -0
  86. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/api/test_api.py +0 -0
  87. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/api/test_api_endpoint.py +0 -0
  88. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/api/test_config_pointer.py +0 -0
  89. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/api/test_targets.py +0 -0
  90. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/cloud/__init__.py +0 -0
  91. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/cloud/uploader/__init__.py +0 -0
  92. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/cloud/uploader/datafiles/__init__.py +0 -0
  93. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/cloud/uploader/datafiles/test_uploader_errors.py +0 -0
  94. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/cloud/uploader/datafiles/test_uploader_full_process.py +0 -0
  95. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/cloud/uploader/datafiles/test_uploader_init.py +0 -0
  96. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/cloud/uploader/datafiles/test_uploader_prepare.py +0 -0
  97. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/cloud/uploader/datafiles/test_uploader_upload.py +0 -0
  98. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/conftest.py +0 -0
  99. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/fixtures/file1.fits +0 -0
  100. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_alpaca_probe.py +0 -0
  101. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_cli.py +0 -0
  102. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_cli_api_commands.py +0 -0
  103. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_docgen.py +0 -0
  104. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_hosting_backups_install_dir.py +0 -0
  105. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_hosting_backups_restore.py +0 -0
  106. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_hosting_check.py +0 -0
  107. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_hosting_composedoc.py +0 -0
  108. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_hosting_lifecycle.py +0 -0
  109. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_hosting_local.py +0 -0
  110. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_hosting_stack.py +0 -0
  111. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_hosting_token.py +0 -0
  112. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_hosting_utils_secret_key.py +0 -0
  113. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_imagesources_autostart.py +0 -0
  114. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_imagesources_commands.py +0 -0
  115. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_imagesources_detection.py +0 -0
  116. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_imagesources_mdns.py +0 -0
  117. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_imagesources_network.py +0 -0
  118. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_imagesources_proxy.py +0 -0
  119. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_imagesources_store.py +0 -0
  120. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/test_imagesources_webcam.py +0 -0
  121. {arcsecond-4.3.2 → arcsecond-4.3.3}/tests/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: arcsecond
3
- Version: 4.3.2
3
+ Version: 4.3.3
4
4
  Summary: CLI for arcsecond.io
5
5
  Project-URL: Homepage, https://github.com/arcsecond-io/cli
6
6
  Project-URL: Issues, https://github.com/arcsecond-io/cli/issues
@@ -8,7 +8,16 @@ from arcsecond.api.constants import API_AUTH_PATH_VERIFY, API_AUTH_PATH_VERIFY_P
8
8
  from arcsecond.errors import ArcsecondError
9
9
 
10
10
  SAFE_METHODS = ["GET", "OPTIONS"]
11
- WRITABLE_MEMBERSHIPS = ["superadmin", "admin", "member"]
11
+
12
+ # The portal roles allowed to write. Both "owner" and "superadmin" are listed
13
+ # because they are the same role: the backend renamed "superadmin" to "owner",
14
+ # and this tool talks to installations on either side of that update.
15
+ # Observatories update the tool independently of their installation, so a
16
+ # freshly updated tool can still be pointed at an installation that has not
17
+ # been updated yet and answers "superadmin".
18
+ #
19
+ # "superadmin" can go once no supported installation predates the rename.
20
+ WRITABLE_MEMBERSHIPS = ["owner", "superadmin", "admin", "member"]
12
21
 
13
22
 
14
23
  class ArcsecondAPIEndpoint(object):
@@ -11,6 +11,7 @@ class ArcsecondTargetListsResource(ArcsecondAPIEndpoint):
11
11
  "id",
12
12
  "pk",
13
13
  "object",
14
+ "coordinates",
14
15
  "name",
15
16
  "identifier",
16
17
  "target_class",
@@ -116,9 +116,12 @@ def _plan_manual(
116
116
  ) -> "ArcsecondTargetPayloadPlan":
117
117
  """The plan for coordinates the user gave us themselves.
118
118
 
119
- The backend takes manual coordinates only as an 'AstronomicalObject', so
120
- that class is assumed here and anything inferred is set aside — with a
121
- warning, since silently ignoring what was inferred would be worse.
119
+ They go as the target's own `coordinates`, which take precedence over the
120
+ catalogue's — offset or not, the user is assumed right — and need no
121
+ object: the backend names one after the fact when the catalogue knows the
122
+ name. Only an 'AstronomicalObject' may carry them, so that class is
123
+ assumed here and anything inferred is set aside — with a warning, since
124
+ silently ignoring what was inferred would be worse.
122
125
  """
123
126
  if user_target_class and user_target_class != TARGET_CLASS_ASTRONOMICAL_OBJECT:
124
127
  errors.append(
@@ -142,11 +145,7 @@ def _plan_manual(
142
145
  errors.append("Manual coordinates require a target name.")
143
146
 
144
147
  payload["target_class"] = effective_target_class
145
- payload["mode"] = TARGET_MODE_MANUAL
146
- payload["object"] = {
147
- "name": effective_name or effective_identifier,
148
- "equatorial_coordinates": effective_coordinates,
149
- }
148
+ payload["coordinates"] = effective_coordinates
150
149
 
151
150
  return ArcsecondTargetPayloadPlan(
152
151
  payload=payload,
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "arcsecond"
7
- version = "4.3.2"
7
+ version = "4.3.3"
8
8
  authors = [
9
9
  { name = "Cedric Foellmi", email = "cedric@arcsecond.io" },
10
10
  ]
@@ -4,6 +4,7 @@ from pathlib import Path
4
4
  import pytest
5
5
 
6
6
  from arcsecond.api.config import CONFIG_DIR_ENV_VAR, ArcsecondConfig
7
+ from arcsecond.api.endpoint import WRITABLE_MEMBERSHIPS
7
8
  from arcsecond.errors import ArcsecondError
8
9
  from arcsecond.options import State
9
10
  from tests.utils import random_string, save_test_credentials
@@ -145,11 +146,22 @@ def test_config_memberships():
145
146
  config = ArcsecondConfig(api_name=random_api_name)
146
147
  assert config.memberships == {}
147
148
  ms = [
148
- {"organisation": "oma", "role": "superadmin"},
149
+ {"organisation": "oma", "role": "owner"},
149
150
  {"organisation": "arcsecond", "role": "member"},
150
151
  ]
151
152
  config.save_memberships(ms)
152
- assert config.memberships == {"oma": "superadmin", "arcsecond": "member"}
153
+ assert config.memberships == {"oma": "owner", "arcsecond": "member"}
154
+
155
+
156
+ def test_owner_membership_is_writable():
157
+ assert "owner" in WRITABLE_MEMBERSHIPS
158
+
159
+
160
+ def test_superadmin_membership_is_still_writable():
161
+ # An installation that predates the rename of "superadmin" to "owner"
162
+ # still answers with the old name, and the tool must keep treating it as
163
+ # the same role until no supported installation does.
164
+ assert "superadmin" in WRITABLE_MEMBERSHIPS
153
165
 
154
166
 
155
167
  def test_config_access_key():
@@ -192,10 +204,8 @@ def test_default_logged_in_state():
192
204
  def test_default_logged_in_with_membership_state():
193
205
  random_api_name = random_string()
194
206
  save_test_credentials(
195
- random_api_name, "cedric", [{"organisation": "saao", "role": "superadmin"}]
207
+ random_api_name, "cedric", [{"organisation": "saao", "role": "owner"}]
196
208
  )
197
209
  assert ArcsecondConfig(api_name=random_api_name).is_logged_in is True
198
210
  assert ArcsecondConfig(api_name=random_api_name).username == "cedric"
199
- assert ArcsecondConfig(api_name=random_api_name).memberships == {
200
- "saao": "superadmin"
201
- }
211
+ assert ArcsecondConfig(api_name=random_api_name).memberships == {"saao": "owner"}
@@ -330,13 +330,17 @@ def test_failed_recreate_reports_but_keeps_the_new_password(tmp_path, monkeypatc
330
330
  assert "password was changed successfully" in result.output
331
331
 
332
332
 
333
- def test_the_data_worker_is_recreated_only_where_the_compose_file_has_it(tmp_path, monkeypatch):
333
+ def test_the_data_worker_is_recreated_only_where_the_compose_file_has_it(
334
+ tmp_path, monkeypatch
335
+ ):
334
336
  """docker-compose.yml 7.3 added it; naming it on an older install would
335
337
  make `docker compose up` fail outright."""
336
338
  monkeypatch.chdir(tmp_path)
337
339
  compose = Path(tmp_path) / "docker-compose.yml"
338
340
 
339
- compose.write_text("services:\n worker:\n container_name: arcsecond-worker\n", encoding="utf-8")
341
+ compose.write_text(
342
+ "services:\n worker:\n container_name: arcsecond-worker\n", encoding="utf-8"
343
+ )
340
344
  assert database._services_to_recreate() == ["backend", "worker", "beat"]
341
345
 
342
346
  compose.write_text(
@@ -344,4 +348,10 @@ def test_the_data_worker_is_recreated_only_where_the_compose_file_has_it(tmp_pat
344
348
  " # >>> arcsecond:alerts\n alerts:\n # <<< arcsecond:alerts\n",
345
349
  encoding="utf-8",
346
350
  )
347
- assert database._services_to_recreate() == ["backend", "worker", "beat", "dataworker", "alerts"]
351
+ assert database._services_to_recreate() == [
352
+ "backend",
353
+ "worker",
354
+ "beat",
355
+ "dataworker",
356
+ "alerts",
357
+ ]
@@ -13,11 +13,14 @@ def test_plan_target_payload_uses_manual_astroobject_when_coordinates_are_provid
13
13
  assert plan.target_class == "AstronomicalObject"
14
14
  assert plan.mode == "manual"
15
15
  assert plan.payload["target_class"] == "AstronomicalObject"
16
- assert plan.payload["mode"] == "manual"
17
- assert plan.payload["object"]["equatorial_coordinates"] == {
16
+ # The user's coordinates are the target's own; no object is sent, the
17
+ # backend names one when the catalogue knows the name.
18
+ assert plan.payload["coordinates"] == {
18
19
  "right_ascension": 344.366,
19
20
  "declination": 20.768,
20
21
  }
22
+ assert "mode" not in plan.payload
23
+ assert "object" not in plan.payload
21
24
  assert "ignored" in plan.warnings[0]
22
25
 
23
26
 
@@ -155,7 +155,7 @@ wheels = [
155
155
 
156
156
  [[package]]
157
157
  name = "arcsecond"
158
- version = "4.3.2"
158
+ version = "4.3.3"
159
159
  source = { editable = "." }
160
160
  dependencies = [
161
161
  { name = "alpyca" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes