Skip to content

Instantly share code, notes, and snippets.

@TerrorBite
Created March 26, 2021 03:31
Show Gist options
  • Save TerrorBite/0443df60f85c52325282a08cd8a7b882 to your computer and use it in GitHub Desktop.
Save TerrorBite/0443df60f85c52325282a08cd8a7b882 to your computer and use it in GitHub Desktop.
from typing import Dict, Any, Type, TypeVar, Optional, Sequence, Union
from contextlib import contextmanager
T = TypeVar
class NamedConstantMeta(type):
def __init__(cls, *args, **kwargs):
super().__init__(*args, **kwargs)
#: This class attribute will be the dict mapping constant names to their constants.
cls._constants: Dict[str, Any] = {}
def __getitem__(cls: Type[T], name: str) -> T:
# This will naturally raise a KeyError if the constant does not exist
return cls._constants[name]
def __contains__(cls, name: str) -> bool:
return name in cls._constants
class NamedConstant(metaclass=NamedConstantMeta):
"""
Each instance of this class can be used as a constant.
Create a constant by passing the name, e.g. ``MYCONST = NamedConstant('MYCONST')``.
Attempting to create a duplicate will raise a `ValueError`.
Constants are equal only to themselves; in other words, the
expression ``x == const`` is equivalent to ``x is const``.
The name of a constant can be retrieved using the name attribute.
Existing constants can be retrieved by name using the item accessor syntax with the class;
for example, ``NamedConstant['SOME_CONSTANT']``. This is useful for retrieving constants
which have been serialised by name. A `KeyError` will be raised if there is no such constant.
You can check if a constant exists the standard way, e.g. ``'SOME_CONSTANT' in NamedConstant``.
:param name: The name of the constant to create.
:raises ValueError: if there is already a constant with that name.
"""
def __init__(self, name: str):
if name in self._constants:
raise ValueError(f"There is already a NamedConstant called {name!r}")
self._constants[name] = self
self.__name__: str = name
@property
def name(self) -> str:
return self.__name__
def __eq__(self, other):
return other is self
def __hash__(self):
return id(self)
@contextmanager
def should_raise(exc_type: Type[BaseException], reason: Optional[str]=None):
"""
Used for testing, to assert that an exception is raised.
:param exc_type: Expect this type of exception.
:param reason: Optional. If provided, check that the string value of the exception is this string.
:raises AssertionError: If the code does not raise the expected exception, or if a reason was provided but the
text of the raised exception doesn't match.
"""
try:
yield None
except exc_type as e: # The expected exception was raised. Yay!
if reason is not None and str(e) != reason:
raise AssertionError(
f"Exception didn't have the expected message\n Actual: {str(e)!r}\nExpected: {reason!r}"
) from e
except BaseException as e: # Catch even things like SystemExit, this is intentional
raise AssertionError(f"Expected {exc_type!r}, but {type(e)!r} was raised instead") from e
else: # Code didn't raise any exception at all
raise AssertionError(f"Expected {exc_type!r}, but no exception was raised")
if __name__ == '__main__':
# Create two constants for testing purposes
const1 = NamedConstant('const1')
const2 = NamedConstant('const2')
# Make sure duplicates can't be created
with should_raise(ValueError, "There is already a NamedConstant called 'const1'"):
NamedConstant('const1')
# Test identity
assert const1 is const1
assert const1 is not const2
# Test equality
assert const1 == const1
assert const1 != const2
assert const1 != 'const1'
# Test that the name can be retrieved
assert const1.name == 'const1'
# Test that constants can be retrieved by name
assert NamedConstant['const1'] is const1
with should_raise(KeyError, "'nonexistent'"):
nonexistent = NamedConstant['nonexistent']
# Test that you can check if constants exist
assert 'const1' in NamedConstant
assert 'const3' not in NamedConstant
# Check that constants are hashable (the hash should be the ID)
assert hash(const1) == id(const1)
# Check that constants are usable as keys, and don't collide with their names
d = {const1: 1, const2: 2, 'const1': 3}
assert d[const1] == 1
assert d[const2] == 2
assert d['const1'] == 3
print("All tests succeeded")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment