fastprocesses 0.22.2__tar.gz → 0.22.4__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 (33) hide show
  1. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/PKG-INFO +2 -2
  2. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/README.md +1 -1
  3. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/pyproject.toml +1 -1
  4. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/api/manager.py +11 -1
  5. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/api/router.py +10 -6
  6. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/core/base_process.py +5 -1
  7. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/core/models.py +1 -4
  8. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/core/output_schema_resolver.py +11 -1
  9. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/worker/chord_tasks.py +2 -1
  10. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/AUTHORS.md +0 -0
  11. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/__init__.py +0 -0
  12. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/api/__init__.py +0 -0
  13. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/api/server.py +0 -0
  14. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/common.py +0 -0
  15. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/core/__init__.py +0 -0
  16. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/core/cache.py +0 -0
  17. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/core/config.py +0 -0
  18. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/core/exceptions.py +0 -0
  19. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/core/logging.py +0 -0
  20. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/core/output_protocol.py +0 -0
  21. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/core/outputs_handler.py +0 -0
  22. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/core/redis_connection.py +0 -0
  23. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/core/types.py +0 -0
  24. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/processes/__init__.py +0 -0
  25. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/processes/process_registry.py +0 -0
  26. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/py.typed +0 -0
  27. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/static/style.css +0 -0
  28. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/templates/landing.html +0 -0
  29. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/worker/__init__.py +0 -0
  30. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/worker/celery_app.py +0 -0
  31. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/worker/executors.py +0 -0
  32. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/worker/job_status.py +0 -0
  33. {fastprocesses-0.22.2 → fastprocesses-0.22.4}/src/fastprocesses/worker/pipeline.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastprocesses
3
- Version: 0.22.2
3
+ Version: 0.22.4
4
4
  Summary: A library to create a FastAPI-based OGC API Processes wrapper around existing projects.
5
5
  License-File: AUTHORS.md
6
6
  Author: Stefan Schuhart
@@ -39,7 +39,7 @@ A library to create a FastAPI-based OGC API Processes wrapper around existing pr
39
39
 
40
40
  AI helped to create this code.
41
41
 
42
- ## Version: 0.22.2
42
+ ## Version: 0.22.4
43
43
 
44
44
  ### Description
45
45
 
@@ -4,7 +4,7 @@ A library to create a FastAPI-based OGC API Processes wrapper around existing pr
4
4
 
5
5
  AI helped to create this code.
6
6
 
7
- ## Version: 0.22.2
7
+ ## Version: 0.22.4
8
8
 
9
9
  ### Description
10
10
 
@@ -79,7 +79,7 @@ exclude = [
79
79
 
80
80
  [tool.poetry]
81
81
  name = "fastprocesses"
82
- version = "0.22.2"
82
+ version = "0.22.4"
83
83
  description = "A library to create a FastAPI-based OGC API Processes wrapper around existing projects."
84
84
  authors = ["Stefan Schuhart <stefan.schuhart@gv.hamburg.de>"]
85
85
  readme = "README.md"
@@ -508,7 +508,17 @@ class ProcessManager:
508
508
  # Avoids jsonable_encoder + model_dump + json.dumps — up to 4 full
509
509
  # Python-level passes through the input data — before returning 201.
510
510
  # Cache lookup is handled by the worker (see find_result_in_cache).
511
- return AsyncExecutionStrategy(self).execute_raw(process_id, raw_body)
511
+ response = AsyncExecutionStrategy(self).execute_raw(process_id, raw_body)
512
+ if isinstance(response, ProcessExecResponse):
513
+ # Persist the original requested outputs and response mode so
514
+ # GET /jobs/{job_id}/results can honour per-request format
515
+ # preferences rather than always returning every output.
516
+ request_meta = {
517
+ "outputs": data.model_dump(mode="json", include={"outputs"})["outputs"],
518
+ "response": data.response,
519
+ }
520
+ self.job_status_cache.put(f"job_request:{response.jobID}", request_meta)
521
+ return response
512
522
 
513
523
  # Sync path: build CalculationTask for cache key and result retrieval.
514
524
  # Sync execution is intended for fast/small jobs where this overhead is acceptable.
@@ -383,14 +383,18 @@ def get_router(
383
383
  process = process_manager.process_registry.get_process(process_id)
384
384
  result_class = _get_result_class(process)
385
385
  if result_class is not None and isinstance(result, dict):
386
- # Retrieve the original outputs + response mode from the job record.
387
- # These are stored in the CalculationTask that was submitted with the job.
388
- # For now fall back to returning all outputs in document mode when
389
- # the job record doesn't carry per-request format preferences.
386
+ # Retrieve the original requested outputs and response mode
387
+ # that were stored when the job was submitted. Falls back
388
+ # to {} (all outputs, document mode) for legacy job records.
389
+ job_request = process_manager.job_status_cache.get(
390
+ f"job_request:{job_id}"
391
+ )
392
+ requested_outputs = (job_request or {}).get("outputs") or {}
393
+ response_mode = (job_request or {}).get("response") or "document"
390
394
  return serialize_result(
391
395
  result_class.model_validate(result),
392
- {}, # empty → resolve all described outputs
393
- "document",
396
+ requested_outputs,
397
+ response_mode,
394
398
  process.process_description,
395
399
  )
396
400
  return JSONResponse(content=result)
@@ -470,6 +470,7 @@ class BaseParallelProcess(BaseProcess, ABC):
470
470
  @abstractmethod
471
471
  def merge_results(
472
472
  self, results: List[Dict[str, Any]],
473
+ exec_body: Dict[str, Any],
473
474
  job_progress_callback: JobProgressCallback | None = None,
474
475
  ) -> BaseProcessResult:
475
476
  """
@@ -479,6 +480,9 @@ class BaseParallelProcess(BaseProcess, ABC):
479
480
  results: List of partial results. Each element is the ``dict``
480
481
  produced by serialising the ``BaseModel`` returned from
481
482
  ``execute_single`` (i.e. the output of ``model.model_dump()``).
483
+ exec_body: The original ``exec_body`` dict passed to ``execute``.
484
+ Gives the merge step access to the raw inputs without requiring
485
+ them to be smuggled through partial results.
482
486
 
483
487
  Returns:
484
488
  A ``BaseProcessResult`` instance holding the final output values.
@@ -516,7 +520,7 @@ class BaseParallelProcess(BaseProcess, ABC):
516
520
  return await p
517
521
  partial = asyncio.run(_await())
518
522
  raw_results.append(partial.model_dump(exclude_none=True))
519
- return self.merge_results(raw_results)
523
+ return self.merge_results(raw_results, exec_body)
520
524
 
521
525
 
522
526
  # ---------------------------------------------------------------------------
@@ -231,10 +231,7 @@ def deserialize_json(value: Any) -> Any:
231
231
 
232
232
  class CalculationTask(BaseModel):
233
233
  inputs: Annotated[Dict[str, Any], AfterValidator(deserialize_json)]
234
- outputs: (
235
- Annotated[dict[str, OutputControl], AfterValidator(deserialize_json)]
236
- | None
237
- ) = None
234
+ outputs: dict[str, OutputControl] | None = None
238
235
  response: ResponseType = ResponseType.RAW
239
236
 
240
237
  def _hash_dict(self):
@@ -87,10 +87,20 @@ def _default_media_type(schema: Schema) -> str | None:
87
87
  return preferred_media_type
88
88
 
89
89
  # None of the preferred types matched — return whatever the schema advertises
90
- return next(
90
+ advertised_media_type = next(
91
91
  (media_type for media_type in candidate_media_types if media_type is not None),
92
92
  None,
93
93
  )
94
+ if advertised_media_type is not None:
95
+ return advertised_media_type
96
+
97
+ # OGC examples frequently describe JSON-native outputs (array/object/number
98
+ # etc.) without explicit contentMediaType/format hints. Treat these as
99
+ # application/json by default so resolver behavior matches spec examples.
100
+ if schema.oneOf is None:
101
+ return "application/json"
102
+
103
+ return None
94
104
 
95
105
 
96
106
  def _is_binary(schema: Schema) -> bool:
@@ -185,7 +185,8 @@ def finalize_parallel(
185
185
  update_job_status(
186
186
  job_id, 95, "Merging parallel results.", JobStatusCode.RUNNING
187
187
  )
188
- merge_result = process.merge_results(actual_results)
188
+ exec_body: dict = original_input or {}
189
+ merge_result = process.merge_results(actual_results, exec_body)
189
190
  merged = merge_result.model_dump(mode="json")
190
191
 
191
192
  try: