4

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?

2
  • Is your question how you can insert a variable in a string, or was there some particular problem specifically related to creating an Enum class? Commented Jul 31, 2022 at 20:43
  • @mkrieger1 it's more of a design issue, so it's coser to your second option: how to create a some Enum class considering a dynamic value like url Commented Jul 31, 2022 at 20:54

2 Answers 2

4
+250

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
Sign up to request clarification or add additional context in comments.

2 Comments

Other than those minor issues, it's a clever solution: recreating the Enums when you instantiate a Namespace.
@EthanFurman indeed , I was missing the Enum import
1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.