Skip to content

Some recommendations when raising warnings and exceptions #59

Description

@framunoz

I have noticed that in several modules warnings and exceptions are being thrown in a very general way. For example:

  • In the module ee_extra/QA/clouds.py you can find the following code:
    platformDict = _get_platform_STAC(x)

    if platformDict["platform"] not in list(lookup.keys()):
        warnings.warn("This platform is not supported for cloud masking.")
        return x

It could be changed to:

    platformDict = _get_platform_STAC(x)
    platform = platformDict["platform"]

    if platform not in list(lookup.keys()):
        warnings.warn(f"Platform {platform} is not supported for cloud masking.")
        return x

To make the message more descriptive. Moreover, all the code could be refactored by including the platform variable.

  • In the ee_extra/STAC/utils.py module, if the args argument does not have a "system:id", then it would throw the exception at the end, but that would be very confusing to the client using this functionality. Also, throwing a generic Exception is not the best way to handle exceptions.

That said, for this module, I propose the following implementation:

import ...  # etc...

# New custom exceptions
class ElementWithoutIdException(Exception):
    """Raised when an element does not have an ID."""

    def __init__(self, elem):
        super().__init__("Element does not have an 'system:id'.")
        self.elem = elem

class PlatformNotSupportedError(Exception):
    """Raised when a platform is not supported."""

    def __init__(self, platform: str):
        super().__init__(f"Platform '{platform}' not supported.")
        self.platform = platform

def _get_platform_STAC(args: Union[ee.Image, ee.ImageCollection]) -> dict:
    ...

    # Line 25
    ID = args.get("system:id").getInfo()
    if ID is None:
        raise ElementWithoutIdException(args)

    ...

    # line 50
    if plt is None:
        raise PlatformNotSupportedError(plt)

    ...

These custom exceptions have the advantage of also including the elements that caused the exception to be thrown for use in exception handling. This code exemplifies this:

class CustomException(Exception):
    def __init__(self, arg):
        super().__init__(f"Look at this arg!: '{arg}'")
        self.arg = arg

try:
    raise CustomException("A dummy arg")
except CustomException as e:
    print(f"Now a know the arg: '{e.arg}'")
>>> Now a know the arg: 'A dummy arg'

If you wish, I can open a PR to include these new changes, and try to find some other cases that are out there. Have a happy day!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions