labthings / labthings/labthings-fastapi

Suport ellipsis as a option for action inputs, or another way to specifiy "not set" which isn't "None"

Open
#178 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
9
Forks
4
PR merge metrics
No merged PRs in 30d

Description

When writing the Camera capture functionality for the OpenFlexure microscope we need to support multiple cameras. Writing some generic higher level camera operations as the BaseCamera Thing requires calling internal methods on each camera.

One arguments is wait, for the picamera wait of None has a meaning, our default is 0.9. I would like to be able to do:

    @lt.thing_action
    def capture_jpeg(
        self,
        metadata: lt.deps.GetThingStates,
        logger: lt.deps.InvocationLogger,
        stream_name: str = "main",
        wait: Optional[float | EllipsisType] = ...,
    ) -> JPEGBlob:
        """Acquire one image from the camera as a JPEG.

        This will use the internal capture image functionally of capture_image if
        the specific camera being used.

        :param metadata: LabThings GetThingStates dependency, automatically injected.
        :param logger: LabThings InvocationLogger dependency, automatically injected.
        :param stream_name: A stream name supported by this camera.
        :param wait: (Optional, float) Set a timeout in seconds. If not set it will
            use the default for the underlying camera.
        """
        fname = datetime.now().strftime("%Y-%m-%d-%H%M%S.jpeg")
        directory = tempfile.TemporaryDirectory()
        jpeg_path = os.path.join(directory.name, fname)

        # Using Ellipsis to specify no input specified. As `None` set for wait may
        # have a meaning as it does for the Picamera. If wait is Ellipsis then
        # do not specify.
        if wait is Ellipsis:
            img = self.capture_image(stream_name)
        else:
            img = self.capture_image(stream_name, wait)
        self._save_capture(
            jpeg_path=jpeg_path,
            image=img,
            metadata=metadata,
            logger=logger,
        )

        return JPEGBlob.from_temporary_directory(directory, fname)

However, I get the following Pydantic error due to the Ellipsis:

fastapi.exceptions.FastAPIError: Invalid args for response field! Hint: check that typing.Union[float, ellipsis, NoneType] is a valid Pydantic field type. If you are using a return type annotation that is not a valid Pydantic field (e.g. Union[Response, dic...

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the action input handling and the FastAPI/Pydantic validation path described by the error. Trace how annotated defaults and unions are converted into request fields; done means an action can distinguish an omitted value from an explicit None without triggering the reported validation error, while preserving existing input behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
fastapi, python
Domain
api, backend
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.