Dynamic enum values on nested classes with Python
Question:
Consider the following enum
class:
from enum import Enum
class Namespace:
class StockAPI(Enum):
ITEMS = "{url}/items"
INVENTORY = "{url}/inventory"
class CustomerAPI(Enum):
USERS = "{url}/users"
PURCHASES = "{url}/purchases"
def __init__(self, url):
self.url = url
I am trying to make url
a dynamic value for each enum
class.
What can I do here so that I can call some enum
class in one of the following ways:
Namespace.StockAPI.ITEMS.value
would return http://localhost/items
?
Namespace(url="http://localhost").StockAPI.ITEMS.value
would also return http://localhost/items
Is this possible to do without doing variable interpolation each time I access each enum
property? Could factory
pattern be of any help here?
Answers:
use f-string:
ITEMS = "{}/items".format(url)
and so on,
but if you use classes, then add new attribute and call it in f-string:
class MyClass:
url = "htpp://www.some.thing"
obj = MyClass()
ITEMS = "{0.url}/items".format(obj)
if you don’t have same names, it is possible to implement it without any Enum:
class Namespace:
def __init__(self, url):
USERS = "{}/users".format(url)
PURCHASES = "{}/purchases".format(url)
ITEMS = "{}/items".format(url)
INVENTORY = "{}/purchases".format(url)
obj = Namespace("https://www.some.news")
print(obj.USERS) # https://www.some.news/users
print(obj.PURCHASES) # https://www.some.news/purchases
print(obj.ITEMS) # https://www.some.news/items
print(obj.INVENTORY) # https://www.some.news/inventory
I did it the following way, while keeping the inner enum
classes:
from enum import Enum
class Namespace:
class StockAPI(Enum):
ITEMS = "{url}/items"
INVENTORY = "{url}/inventory"
class CustomerAPI(Enum):
USERS = "{url}/users"
PURCHASES = "{url}/purchases"
def __init__(self, url: str):
attrs = (getattr(self, attr) for attr in dir(self))
enums = (a for a in attrs if isinstance(a, type) and issubclass(a, Enum))
for enum in enums:
kv = {e.name: e.value.format(url=url) for e in enum}
setattr(self, enum.__name__, Enum(enum.__name__, kv))
print(Namespace(url="http://test.com").StockAPI.ITEMS.value)
# http://test.com/items
Consider the following enum
class:
from enum import Enum
class Namespace:
class StockAPI(Enum):
ITEMS = "{url}/items"
INVENTORY = "{url}/inventory"
class CustomerAPI(Enum):
USERS = "{url}/users"
PURCHASES = "{url}/purchases"
def __init__(self, url):
self.url = url
I am trying to make url
a dynamic value for each enum
class.
What can I do here so that I can call some enum
class in one of the following ways:
Namespace.StockAPI.ITEMS.value
would returnhttp://localhost/items
?Namespace(url="http://localhost").StockAPI.ITEMS.value
would also returnhttp://localhost/items
Is this possible to do without doing variable interpolation each time I access each enum
property? Could factory
pattern be of any help here?
use f-string:
ITEMS = "{}/items".format(url)
and so on,
but if you use classes, then add new attribute and call it in f-string:
class MyClass:
url = "htpp://www.some.thing"
obj = MyClass()
ITEMS = "{0.url}/items".format(obj)
if you don’t have same names, it is possible to implement it without any Enum:
class Namespace:
def __init__(self, url):
USERS = "{}/users".format(url)
PURCHASES = "{}/purchases".format(url)
ITEMS = "{}/items".format(url)
INVENTORY = "{}/purchases".format(url)
obj = Namespace("https://www.some.news")
print(obj.USERS) # https://www.some.news/users
print(obj.PURCHASES) # https://www.some.news/purchases
print(obj.ITEMS) # https://www.some.news/items
print(obj.INVENTORY) # https://www.some.news/inventory
I did it the following way, while keeping the inner enum
classes:
from enum import Enum
class Namespace:
class StockAPI(Enum):
ITEMS = "{url}/items"
INVENTORY = "{url}/inventory"
class CustomerAPI(Enum):
USERS = "{url}/users"
PURCHASES = "{url}/purchases"
def __init__(self, url: str):
attrs = (getattr(self, attr) for attr in dir(self))
enums = (a for a in attrs if isinstance(a, type) and issubclass(a, Enum))
for enum in enums:
kv = {e.name: e.value.format(url=url) for e in enum}
setattr(self, enum.__name__, Enum(enum.__name__, kv))
print(Namespace(url="http://test.com").StockAPI.ITEMS.value)
# http://test.com/items