gpp-client 26.7.3__tar.gz → 26.7.3.dev2__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 (113) hide show
  1. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/PKG-INFO +1 -1
  2. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/domains/scheduler.py +31 -1
  3. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/package_environment.py +1 -1
  4. gpp_client-26.7.3.dev2/src/gpp_client/rest/__init__.py +8 -0
  5. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/rest/client.py +57 -1
  6. gpp_client-26.7.3.dev2/src/gpp_client/rest/models.py +89 -0
  7. gpp_client-26.7.3/src/gpp_client/rest/__init__.py +0 -7
  8. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/.gitignore +0 -0
  9. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/LICENSE +0 -0
  10. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/README.md +0 -0
  11. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/graphql/README.md +0 -0
  12. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/pyproject.toml +0 -0
  13. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/__init__.py +0 -0
  14. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/cli/__init__.py +0 -0
  15. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/cli/cli.py +0 -0
  16. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/cli/commands/__init__.py +0 -0
  17. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/cli/commands/attachment.py +0 -0
  18. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/cli/commands/goats.py +0 -0
  19. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/cli/commands/observation.py +0 -0
  20. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/cli/commands/program.py +0 -0
  21. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/cli/commands/scheduler.py +0 -0
  22. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/cli/commands/site_status.py +0 -0
  23. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/cli/commands/target.py +0 -0
  24. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/cli/commands/workflow_state.py +0 -0
  25. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/cli/console.py +0 -0
  26. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/cli/output.py +0 -0
  27. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/cli/utils.py +0 -0
  28. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/client.py +0 -0
  29. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/constants.py +0 -0
  30. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/domains/__init__.py +0 -0
  31. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/domains/atom.py +0 -0
  32. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/domains/attachment.py +0 -0
  33. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/domains/base.py +0 -0
  34. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/domains/goats.py +0 -0
  35. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/domains/observation.py +0 -0
  36. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/domains/program.py +0 -0
  37. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/domains/site_status.py +0 -0
  38. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/domains/target.py +0 -0
  39. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/domains/workflow_state.py +0 -0
  40. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/environment.py +0 -0
  41. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/exceptions.py +0 -0
  42. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/__init__.py +0 -0
  43. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/async_base_client.py +0 -0
  44. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/base_model.py +0 -0
  45. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/base_operation.py +0 -0
  46. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/client.py +0 -0
  47. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/clone_observation.py +0 -0
  48. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/clone_target.py +0 -0
  49. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/create_call_for_proposals.py +0 -0
  50. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/create_observation.py +0 -0
  51. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/create_program.py +0 -0
  52. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/create_target_by_program_id.py +0 -0
  53. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/create_target_by_program_reference.py +0 -0
  54. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/create_target_by_proposal_reference.py +0 -0
  55. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/custom_fields.py +0 -0
  56. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/custom_mutations.py +0 -0
  57. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/custom_queries.py +0 -0
  58. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/custom_typing_fields.py +0 -0
  59. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/delete_call_for_proposals_by_id.py +0 -0
  60. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/delete_observation_by_id.py +0 -0
  61. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/delete_observation_by_reference.py +0 -0
  62. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/delete_program_by_id.py +0 -0
  63. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/delete_target_by_id.py +0 -0
  64. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/enums.py +0 -0
  65. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/exceptions.py +0 -0
  66. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/fragments.py +0 -0
  67. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/get_call_for_proposals.py +0 -0
  68. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/get_calls_for_proposals.py +0 -0
  69. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/get_goats_observations.py +0 -0
  70. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/get_goats_programs.py +0 -0
  71. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/get_observation.py +0 -0
  72. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/get_observation_attachments_by_id.py +0 -0
  73. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/get_observation_attachments_by_reference.py +0 -0
  74. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/get_observation_workflow_state_by_id.py +0 -0
  75. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/get_observation_workflow_state_by_reference.py +0 -0
  76. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/get_observations.py +0 -0
  77. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/get_program_attachments_by_id.py +0 -0
  78. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/get_program_attachments_by_proposal_reference.py +0 -0
  79. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/get_program_attachments_by_reference.py +0 -0
  80. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/get_program_by_id.py +0 -0
  81. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/get_program_by_proposal_reference.py +0 -0
  82. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/get_program_by_reference.py +0 -0
  83. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/get_programs.py +0 -0
  84. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/get_scheduler_all_programs_id.py +0 -0
  85. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/get_scheduler_programs.py +0 -0
  86. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/get_target_by_id.py +0 -0
  87. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/get_targets.py +0 -0
  88. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/input_types.py +0 -0
  89. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/obs_calculation_update.py +0 -0
  90. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/observation_edit.py +0 -0
  91. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/ping.py +0 -0
  92. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/program_edit.py +0 -0
  93. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/restore_call_for_proposals_by_id.py +0 -0
  94. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/restore_observation_by_id.py +0 -0
  95. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/restore_observation_by_reference.py +0 -0
  96. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/restore_program_by_id.py +0 -0
  97. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/restore_target_by_id.py +0 -0
  98. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/scheduler_observations_updates.py +0 -0
  99. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/set_observation_workflow_state.py +0 -0
  100. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/target_edit.py +0 -0
  101. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/update_call_for_proposals_by_id.py +0 -0
  102. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/update_calls_for_proposals.py +0 -0
  103. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/update_observation_by_id.py +0 -0
  104. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/update_observation_by_reference.py +0 -0
  105. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/update_observations.py +0 -0
  106. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/update_program_by_id.py +0 -0
  107. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/update_programs.py +0 -0
  108. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/update_target_by_id.py +0 -0
  109. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/generated/update_targets.py +0 -0
  110. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/logging_utils.py +0 -0
  111. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/rest/utils.py +0 -0
  112. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/settings.py +0 -0
  113. {gpp_client-26.7.3 → gpp_client-26.7.3.dev2}/src/gpp_client/urls.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gpp-client
3
- Version: 26.7.3
3
+ Version: 26.7.3.dev2
4
4
  Summary: Gemini Program Platform client.
5
5
  Project-URL: Homepage, https://github.com/gemini-hlsw/gpp-client
6
6
  Project-URL: Source, https://github.com/gemini-hlsw/gpp-client
@@ -8,6 +8,7 @@ from datetime import datetime
8
8
  from typing import Any, AsyncIterator
9
9
 
10
10
  from gpp_client.domains.base import BaseDomain
11
+ from gpp_client.rest.models import VisibilityChanges, parse_visibility_changes
11
12
  from gpp_client.generated import SchedulerObservationsUpdates
12
13
  from gpp_client.generated.get_scheduler_all_programs_id import (
13
14
  GetSchedulerAllProgramsId,
@@ -252,7 +253,7 @@ class SchedulerDomain(BaseDomain):
252
253
  if observations:
253
254
  async with self._rest as client:
254
255
  atom_digest_response = (
255
- await client._get_atom_digests(observations)
256
+ await client.get_atom_digests(observations)
256
257
  ).split("\n")
257
258
  obs_atoms_mapping = self._parse_atom_digest(atom_digest_response)
258
259
  else:
@@ -288,6 +289,35 @@ class SchedulerDomain(BaseDomain):
288
289
  response = await self.get_program_ids(today=today)
289
290
  return [(p.reference.label, p.id) for p in response.programs.matches]
290
291
 
292
+ async def get_visibility_changes(self, since: datetime) -> VisibilityChanges:
293
+ """
294
+ Get observations and targets with visibility changes since a time.
295
+
296
+ Queries the ODB ``/scheduler/visibility-changes`` REST endpoint, which
297
+ reports entities whose visibility-relevant inputs changed at or after
298
+ ``since``.
299
+
300
+ Parameters
301
+ ----------
302
+ since : datetime
303
+ Return entities changed at or after this time. Naive datetimes are
304
+ assumed to be UTC.
305
+
306
+ Returns
307
+ -------
308
+ VisibilityChanges
309
+ Changed observation and target GIDs plus the latest change
310
+ timestamp reported by the endpoint.
311
+
312
+ Raises
313
+ ------
314
+ aiohttp.ClientError
315
+ For HTTP errors, connection failures, or timeouts.
316
+ """
317
+ async with self._rest as client:
318
+ body = await client.get_visibility_changes(since)
319
+ return parse_visibility_changes(body)
320
+
291
321
  async def subscribe_to_calculation_updates(
292
322
  self,
293
323
  ) -> AsyncIterator[SchedulerObservationsUpdates]:
@@ -2,4 +2,4 @@
2
2
  Package-level environment constant for generated client code.
3
3
  """
4
4
 
5
- PACKAGE_ENVIRONMENT = "PRODUCTION"
5
+ PACKAGE_ENVIRONMENT = "DEVELOPMENT"
@@ -0,0 +1,8 @@
1
+ """
2
+ REST API client for non-GraphQL requests.
3
+ """
4
+
5
+ from .client import RESTClient
6
+ from .models import VisibilityChanges, parse_visibility_changes
7
+
8
+ __all__ = ["RESTClient", "VisibilityChanges", "parse_visibility_changes"]
@@ -8,6 +8,7 @@ import asyncio
8
8
  import gzip
9
9
  import logging
10
10
  import ssl
11
+ from datetime import datetime, timezone
11
12
 
12
13
  import aiohttp
13
14
  import certifi
@@ -102,11 +103,32 @@ class RESTClient:
102
103
  async def __aexit__(self, exc_type, exc_val, exc_tb):
103
104
  await self.close()
104
105
 
105
- async def _get_atom_digests(
106
+ async def get_atom_digests(
106
107
  self, observation_ids: list[str], accept_gzip: bool = True
107
108
  ) -> str:
108
109
  """
109
110
  Request atom digests for the given observation IDs.
111
+
112
+ Parameters
113
+ ----------
114
+ observation_ids : list[str]
115
+ (internal) IDs of the observation to request.
116
+
117
+ accept_gzip : bool
118
+ Endpoint allows to return a gzip-compressed representation of the
119
+ complete atoms digest in the case of being too big.
120
+
121
+ Returns
122
+ -------
123
+ str
124
+ TSV data as string, one row per line.
125
+
126
+ Raises
127
+ ------
128
+ aiohttp.ClientResponseError
129
+ For HTTP error responses.
130
+ aiohttp.ClientError
131
+ For connection or timeout failures.
110
132
  """
111
133
  headers = {}
112
134
  if accept_gzip:
@@ -145,3 +167,37 @@ class RESTClient:
145
167
  return await response.text()
146
168
  else:
147
169
  return await response.text()
170
+
171
+ async def get_visibility_changes(self, since: datetime) -> str:
172
+ """
173
+ Request observations and targets with visibility changes since a time.
174
+
175
+ Parameters
176
+ ----------
177
+ since : datetime
178
+ Return entities whose visibility-relevant inputs changed at or
179
+ after this time. Naive datetimes are assumed to be UTC.
180
+
181
+ Returns
182
+ -------
183
+ str
184
+ TSV data as string, one ``<gid>\\t<iso8601-timestamp>`` per line.
185
+
186
+ Raises
187
+ ------
188
+ aiohttp.ClientResponseError
189
+ For HTTP error responses.
190
+ aiohttp.ClientError
191
+ For connection or timeout failures.
192
+ """
193
+ if since.tzinfo is None:
194
+ since = since.replace(tzinfo=timezone.utc)
195
+
196
+ session = await self.get_session()
197
+
198
+ async with session.get(
199
+ "/scheduler/visibility-changes",
200
+ params={"since": since.astimezone(timezone.utc).isoformat()},
201
+ ) as response:
202
+ response.raise_for_status()
203
+ return await response.text()
@@ -0,0 +1,89 @@
1
+ """
2
+ Models and parsers for REST API responses.
3
+ """
4
+
5
+ __all__ = ["VisibilityChanges", "parse_visibility_changes"]
6
+
7
+ import logging
8
+ from dataclasses import dataclass, field
9
+ from datetime import datetime
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+
14
+ @dataclass(frozen=True)
15
+ class VisibilityChanges:
16
+ """
17
+ Observations and targets whose visibility-relevant inputs changed.
18
+
19
+ Attributes
20
+ ----------
21
+ observation_ids : frozenset[str]
22
+ Observation GIDs (``o-`` prefix) with visibility changes.
23
+ target_ids : frozenset[str]
24
+ Target GIDs (``t-`` prefix) with visibility changes.
25
+ max_timestamp : datetime | None
26
+ Latest change timestamp reported by the endpoint, or None when no
27
+ parseable timestamps were returned.
28
+ """
29
+
30
+ observation_ids: frozenset[str] = field(default_factory=frozenset)
31
+ target_ids: frozenset[str] = field(default_factory=frozenset)
32
+ max_timestamp: datetime | None = None
33
+
34
+
35
+ def parse_visibility_changes(body: str) -> VisibilityChanges:
36
+ """
37
+ Parse the TSV body of ``/scheduler/visibility-changes``.
38
+
39
+ Each line is ``<gid>\\t<iso8601-timestamp>`` where the GID prefix
40
+ disambiguate the entity: ``o-`` for observations, ``t-`` for targets.
41
+ Malformed lines and unknown prefixes are skipped with a warning; a bad
42
+ timestamp keeps the GID but does not contribute to ``max_timestamp``.
43
+
44
+ Parameters
45
+ ----------
46
+ body : str
47
+ Raw TSV response body.
48
+
49
+ Returns
50
+ -------
51
+ VisibilityChanges
52
+ Parsed observation/target GIDs and the latest change timestamp.
53
+ """
54
+ observation_ids: set[str] = set()
55
+ target_ids: set[str] = set()
56
+ max_timestamp: datetime | None = None
57
+
58
+ for line in body.splitlines():
59
+ line = line.strip()
60
+ if not line:
61
+ continue
62
+ gid, _, raw_timestamp = line.partition("\t")
63
+ gid = gid.strip()
64
+
65
+ if gid.startswith("o-"):
66
+ observation_ids.add(gid)
67
+ elif gid.startswith("t-"):
68
+ target_ids.add(gid)
69
+ else:
70
+ logger.warning(
71
+ "Skipping visibility-changes line with unknown GID: %r", line
72
+ )
73
+ continue
74
+
75
+ try:
76
+ timestamp = datetime.fromisoformat(
77
+ raw_timestamp.strip().replace("Z", "+00:00")
78
+ )
79
+ except ValueError:
80
+ logger.warning("Unparseable timestamp in visibility-changes line: %r", line)
81
+ continue
82
+ if max_timestamp is None or timestamp > max_timestamp:
83
+ max_timestamp = timestamp
84
+
85
+ return VisibilityChanges(
86
+ observation_ids=frozenset(observation_ids),
87
+ target_ids=frozenset(target_ids),
88
+ max_timestamp=max_timestamp,
89
+ )
@@ -1,7 +0,0 @@
1
- """
2
- REST API client for non-GraphQL requests.
3
- """
4
-
5
- from .client import RESTClient
6
-
7
- __all__ = ["RESTClient"]
File without changes
File without changes
File without changes