import pytest from enum import Enum class ENVVariant(str): __VALID_MEMBERS__ = ["LOCAL", "DEV", "SIT", "UAT", "PREPROD", "PROD"] def __new__(cls, value: str): members = ENVVariant.__VALID_MEMBERS__ if isinstance(value, RollYourOwnNewTypeEnum): value_as_str = str(value.value) else: value_as_str = str(value) if value_as_str not in members: raise ValueError(f"`value` = {value} must be one of `{members}`; `value_as_str` = {value_as_str}") return super().__new__(cls, value_as_str) # why not i write my own `.replace(..)` # yes, you can but how? def my_replace(self, old: "ENVVariant", new: "ENVVariant", count: int=-1): return ENVVariant(str(self).replace(str(old), str(new), count)) class RollYourOwnNewTypeEnum(ENVVariant, Enum): LOCAL = "LOCAL" DEV = "DEV" SIT = "SIT" UAT = "UAT" PREPROD = "PREPROD" PROD = "PROD" def test_ryont_env_replace(): env = RollYourOwnNewTypeEnum.LOCAL # expected outcomes assert env is RollYourOwnNewTypeEnum.LOCAL # pass assert env is not RollYourOwnNewTypeEnum.DEV # pass assert isinstance(env, RollYourOwnNewTypeEnum) # pass # now we try to replace env = env.replace(RollYourOwnNewTypeEnum.LOCAL, RollYourOwnNewTypeEnum.DEV) # we are hoping that it will continue to be a `RollYourOwnNewTypeEnum.DEV` but it is not assert env is not RollYourOwnNewTypeEnum.DEV # pass, no longer a `RollYourOwnNewTypeEnum` assert env is not RollYourOwnNewTypeEnum.LOCAL # pass, no longer a `RollYourOwnNewTypeEnum` assert not isinstance(env, RollYourOwnNewTypeEnum) assert isinstance(env, str) # 'downcast' (?) to `str` with pytest.raises(AssertionError): assert env is RollYourOwnNewTypeEnum.DEV with pytest.raises(AssertionError): assert env is RollYourOwnNewTypeEnum.DEV with pytest.raises(AssertionError): assert isinstance(env, RollYourOwnNewTypeEnum) env = env.replace("DEV", "NotAnEnv") assert env == "NotAnEnv" # this 'shouldn't' pass but it does env = RollYourOwnNewTypeEnum.LOCAL env = env.my_replace(RollYourOwnNewTypeEnum.LOCAL, RollYourOwnNewTypeEnum.PREPROD) assert isinstance(env, str) assert env is RollYourOwnNewTypeEnum.PREPROD assert isinstance(env, RollYourOwnNewTypeEnum)