Skip to content

Refactor to use Enums consistently in PySTAC #231

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
lossyrob opened this issue Oct 30, 2020 · 7 comments
Closed

Refactor to use Enums consistently in PySTAC #231

lossyrob opened this issue Oct 30, 2020 · 7 comments
Labels
best practice Issues that should be addressed for compliance with best practices, but that aren't technically bugs discussion An issue to capture a discussion

Comments

@lossyrob
Copy link
Member

Currently, things like CatalogType, LinkType etc are not enums but constants held in a class. In other places like the SAR extension, we use Enums.

We should be consistent about our usage of enums across the library.

Note that moving from constants to enums would be a pretty big API break, potentially requiring a lot of client code changes. If we were to make that decision, it might be best to provide upgrade scripts to ease some of that API breakage pain.

If you have an opinion on whether or not Enums should be used across the library, please use this issue to voice it!

@lossyrob lossyrob added best practice Issues that should be addressed for compliance with best practices, but that aren't technically bugs discussion An issue to capture a discussion labels Oct 30, 2020
@kylebarron
Copy link
Contributor

As mentioned in the linked issue, I'm a fan of using Enum. One nice thing is that it lets you iterate over the enum easily. For example, say you were making a CLI where you wanted to provide a media type option. Currently you'd have to make the option list manually and keep it up to date. When subclassing from enum, it's much simpler: click.Choice([e.name for e in MediaType], case_sensitive=False)).

potentially requiring a lot of client code changes

Are you referring to code changes inside pystac or in third party libraries? I wouldn't expect many code changes, and if you're using existing classes as de-facto enums, you might not need any...

If you have a class like

class MediaType:
    COG = 'image/tiff; application=geotiff; profile=cloud-optimized'
    GEOJSON = 'application/geo+json'
    GEOPACKAGE = 'application/geopackage+sqlite3'

and you detect media type in code with

if media_type == MediaType.COG

then you need no changes there between the above and

class MediaType(str, Enum):

I'm guessing by backwards incompatible changes, you're referring to the string representation of the enum object? E.g. the current implementation prints the value of the enum

print(MediaType.COG)
# image/tiff; application=geotiff; profile=cloud-optimized

whereas changing to subclassing from Enum by default prints differently:

print(MediaType.COG)
# MediaType.COG

however this is easy to get around by overriding the __str__ method:

class MediaType(str, Enum):
    def __str__(self):
        return str(self.value)

    COG = 'image/tiff; application=geotiff; profile=cloud-optimized'
    GEOJSON = 'application/geo+json'
    GEOPACKAGE = 'application/geopackage+sqlite3'

print(MediaType.COG)
# image/tiff; application=geotiff; profile=cloud-optimized

Any other things that you think wouldn't be backwards-compatible?

@lossyrob
Copy link
Member Author

@kylebarron this all sounds great, and I think it's the direction we should go in. In the PR you referenced you asked if a PR would be accepted - resounding yes!

@lossyrob lossyrob changed the title Use Enums or not consistently in PySTAC Refactor to use Enums consistently in PySTAC Feb 17, 2021
@geospatial-jeff
Copy link

geospatial-jeff commented Feb 17, 2021

I'm on team enum. But there are definitely a few downsides to using them:

  • They don't give you anything you can't already do with python, and they add another thing that a person needs to know to use pystac which maybe goes against the idea of using as few dependencies as possible. But its also used quite a bit (including many geo libs), and part of the python standard lib so I don't think this is that big of a deal.
  • They can't be subclassed, which may be very problematic depending on the use case. Stac-pydantic initially used enums to enforce link relations, MIME types, and a few others but it becomes difficult to extend because you can't subclass the enum.

@lossyrob
Copy link
Member Author

@geospatial-jeff good points - I was thinking about how some of the enum parameters should be annotated as part of #260, and didn't want to "block" passing in arbitrary strings for things like media types and link types that we don't have a complete list of. So I figured making parameters e.g. Union[MediaType, str] would be a good way to avoid restricting users to those types. Are there other ideas on how to get around these downsides?

@geospatial-jeff
Copy link

That is a good solution! Although I think you want to flip the order of the union so the less restrictive type comes first: Union[str, MediaType]

@kylebarron
Copy link
Contributor

Does the order of the Union matter?

@lossyrob
Copy link
Member Author

lossyrob commented May 4, 2021

Closed in #261, Union type for MediaType is added in #309

@lossyrob lossyrob closed this as completed May 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
best practice Issues that should be addressed for compliance with best practices, but that aren't technically bugs discussion An issue to capture a discussion
Projects
None yet
Development

No branches or pull requests

3 participants