Skip to content

Instantly share code, notes, and snippets.

@jnhmcknight
Last active May 19, 2023 15:23
Show Gist options
  • Save jnhmcknight/c6a28b2322dfa475deb9f27d8bda0847 to your computer and use it in GitHub Desktop.
Save jnhmcknight/c6a28b2322dfa475deb9f27d8bda0847 to your computer and use it in GitHub Desktop.
from enum import Enum, EnumMeta
from flask import Flask, current_app
from werkzeug.routing import BaseConverter, ValidationError
def setup_enum_converter(enum_to_convert):
if not isinstance(enum_to_convert, (Enum, EnumMeta,)):
raise ValueError(f'{enum_to_convert.__name__} is not an Enum')
class ConfiguredEnumConverter(BaseConverter):
def to_python(self, value):
try:
return enum_to_convert[value]
except (KeyError, IndexError, ValueError) as exc:
current_app.logger.exception(exc)
raise ValidationError from exc
def to_url(self, obj):
if not isinstance(obj, enum_to_convert):
raise ValidationError()
return obj.name
return ConfiguredEnumConverter
# Can be a static Enum or a dynamic one:
DynamicEnum = Enum('DynamicEnum', {'ONE': 1, 'TWO': 2, 'THREE': 3})
class StaticEnum(Enum):
FOUR = 4
FIVE = 5
SIX = 6
app = Flask(__name__)
# Add the Enum converter to the app's available converters before the route/blueprint that needs it
# `MyDynamicEnum`/`MyStaticEnum` corresponds to the name that we use in the route
app.url_map.converters.update(
MyDynamicEnum=setup_enum_converter(DynamicEnum),
MyStaticEnum=setup_enum_converter(StaticEnum),
)
@app.route('/dynamic/<MyDynamicEnum:param>')
def dynamic_enum(param):
return f'{type(param)}->{param} = {param.value}'
@app.route('/static/<MyStaticEnum:param>')
def static_enum(param):
return f'{type(param)}->{param} = {param.value}'
# On running this mini Flask app, you get:
#
# $ curl http://localhost:5000/static/FIVE
# <enum 'StaticEnum'>->StaticEnum.FIVE: FIVE = 4
#
# $ curl http://localhost:5000/dynamic/ONE
# <enum 'DynamicEnum'>->DynamicEnum.ONE = 1
#
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment