aind-codeocean-dispatch 0.2.0__py3-none-any.whl → 0.2.2__py3-none-any.whl

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.
@@ -6,7 +6,9 @@ counters rather than locks, and no thread is parked per job.
6
6
 
7
7
  Error policy
8
8
  ------------
9
- The SDK's client retries nothing by default, so every 429 or 5xx surfaces here.
9
+ Every 429 or 5xx must surface here, so :func:`run_jobs` works on a copy of the
10
+ client with ``retries=0``: transport-level retries would resend POSTs below this
11
+ policy, and their exhausted retries raise without the status code it reads.
10
12
 
11
13
  - **429** is retried on every call, honouring ``Retry-After``: the server rejected
12
14
  the request without acting on it.
@@ -33,9 +35,13 @@ from typing import TYPE_CHECKING, Any, Literal, TypeVar
33
35
  import requests
34
36
  from aind_code_ocean_pipeline_utils.cache import input_fingerprint
35
37
  from aind_code_ocean_pipeline_utils.process import GracefulExit, check_shutdown
38
+
39
+ # Import paths that exist across supported SDK versions; 0.17 moved the models to
40
+ # ``codeocean.models`` and kept these as re-exports.
41
+ from codeocean.components import Ownership
42
+ from codeocean.computation import Computation, ComputationEndStatus, ComputationState, RunParams
43
+ from codeocean.data_asset import DataAsset, DataAssetParams, DataAssetSearchParams, DataAssetState
36
44
  from codeocean.error import Error as CodeOceanError
37
- from codeocean.models.computation import Computation, ComputationEndStatus, ComputationState, RunParams
38
- from codeocean.models.data_asset import DataAsset, DataAssetParams, DataAssetSearchParams, DataAssetState
39
45
 
40
46
  if TYPE_CHECKING:
41
47
  from codeocean import CodeOcean
@@ -88,8 +94,8 @@ class Job:
88
94
  can depend on it. ``None`` stops at a successful computation.
89
95
  key : str, optional
90
96
  Resume key (see :func:`job_key`), added to the captured asset as
91
- :func:`key_tag`. With ``reuse=True``, a Ready asset carrying it is returned
92
- instead of launching. ``None`` never reuses.
97
+ :func:`key_tag`. With ``reuse=True``, a Ready asset carrying it that the
98
+ caller created is returned instead of launching. ``None`` never reuses.
93
99
  """
94
100
 
95
101
  label: str
@@ -228,7 +234,8 @@ def run_jobs(
228
234
  Parameters
229
235
  ----------
230
236
  client : CodeOcean
231
- Authenticated client.
237
+ Authenticated client. Its own ``retries`` setting is overridden on a copy;
238
+ the caller's client is left unchanged.
232
239
  jobs : Sequence[Job]
233
240
  Launched in order, subject to the cap and pacing.
234
241
  max_in_flight : int, optional
@@ -243,7 +250,9 @@ def run_jobs(
243
250
  capture_retries : int, optional
244
251
  New capture attempts per job after a capture ends in the Failed state.
245
252
  reuse : bool, optional
246
- Return a Ready asset tagged with a job's key instead of launching it.
253
+ Return a Ready asset tagged with a job's key instead of launching it. Only
254
+ assets the caller created count: another user running identical inputs
255
+ produces the same key, and their asset is not the caller's to consume.
247
256
  poll_interval_s : float, optional
248
257
  Seconds between status checks of each running computation.
249
258
  timeout_s : float, optional
@@ -265,7 +274,7 @@ def run_jobs(
265
274
  """
266
275
  _validate(jobs, max_in_flight=max_in_flight, start_retries=start_retries, capture_retries=capture_retries)
267
276
  return _Dispatcher(
268
- client,
277
+ _without_transport_retries(client),
269
278
  jobs,
270
279
  max_in_flight=max_in_flight,
271
280
  launch_interval_s=launch_interval_s,
@@ -278,6 +287,18 @@ def run_jobs(
278
287
  ).run()
279
288
 
280
289
 
290
+ def _without_transport_retries(client: CodeOcean) -> CodeOcean:
291
+ """Return *client*, or a copy with ``retries=0`` if it retries requests itself.
292
+
293
+ The copy opens a new session, so anything mounted on the original's ``session``
294
+ by hand is not carried over.
295
+ """
296
+ if client.retries in (0, None):
297
+ return client
298
+ logger.info("using a copy of the client with retries=0 (was %r); run_jobs retries what is safe", client.retries)
299
+ return dataclasses.replace(client, retries=0)
300
+
301
+
281
302
  def _validate(jobs: Sequence[Job], *, max_in_flight: int | None, start_retries: int, capture_retries: int) -> None:
282
303
  labels = [job.label for job in jobs]
283
304
  if len(set(labels)) != len(labels):
@@ -479,7 +500,7 @@ class _Dispatcher:
479
500
  if slot.next_at > _now():
480
501
  continue
481
502
  tag = key_tag(slot.job.key)
482
- params = DataAssetSearchParams(query=f"tag:{tag}", limit=100)
503
+ params = DataAssetSearchParams(query=f"tag:{tag}", ownership=Ownership.Created, limit=100)
483
504
  try:
484
505
  results = self.client.data_assets.search_data_assets(params)
485
506
  except (CodeOceanError, requests.RequestException) as exc:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: aind-codeocean-dispatch
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Launch, monitor, and capture batches of Code Ocean capsule runs
5
5
  Project-URL: Repository, https://github.com/AllenNeuralDynamics/aind-codeocean-dispatch/
6
6
  Project-URL: Issues, https://github.com/AllenNeuralDynamics/aind-codeocean-dispatch/issues
@@ -12,7 +12,7 @@ License-File: LICENSE
12
12
  Classifier: Programming Language :: Python :: 3
13
13
  Requires-Python: >=3.11
14
14
  Requires-Dist: aind-code-ocean-pipeline-utils>=0.7.1
15
- Requires-Dist: codeocean>=0.17
15
+ Requires-Dist: codeocean>=0.13
16
16
  Description-Content-Type: text/markdown
17
17
 
18
18
  # AIND Code Ocean dispatch
@@ -0,0 +1,7 @@
1
+ aind_codeocean_dispatch/__init__.py,sha256=NcdbegNPvYKWVRArhlkdEL7HP9kof1OOiH8aRcrcszY,660
2
+ aind_codeocean_dispatch/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
3
+ aind_codeocean_dispatch/runner.py,sha256=Zwfvt7NuLxrCrV6t8KPfgiqkdBlV8e6XlcXkkJKwKHk,25344
4
+ aind_codeocean_dispatch-0.2.2.dist-info/METADATA,sha256=LMBckmvXZjxfWyeGaIw-siS4aDAYETmCEnVcWwVWYyg,2797
5
+ aind_codeocean_dispatch-0.2.2.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
6
+ aind_codeocean_dispatch-0.2.2.dist-info/licenses/LICENSE,sha256=zMZxYbR1i_XxgyJP_rPSWKcxY7QtyxUOzbIpowHNjCs,1093
7
+ aind_codeocean_dispatch-0.2.2.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- aind_codeocean_dispatch/__init__.py,sha256=NcdbegNPvYKWVRArhlkdEL7HP9kof1OOiH8aRcrcszY,660
2
- aind_codeocean_dispatch/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
3
- aind_codeocean_dispatch/runner.py,sha256=hMeVmd5v5bWCF_2CQYkNV5HzD_Ywn5eyORzNqQGkHA4,24178
4
- aind_codeocean_dispatch-0.2.0.dist-info/METADATA,sha256=vPbl6NmG66g2-gKqzmGsJkPIeP-wvb5K7ZaacsFL8Rc,2797
5
- aind_codeocean_dispatch-0.2.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
6
- aind_codeocean_dispatch-0.2.0.dist-info/licenses/LICENSE,sha256=zMZxYbR1i_XxgyJP_rPSWKcxY7QtyxUOzbIpowHNjCs,1093
7
- aind_codeocean_dispatch-0.2.0.dist-info/RECORD,,