Simple, easy to use with intuitive APIs, for managing constants in your Python applications.
Project description
truconsts
Version: 0.0.9
truconsts
is a constants management package for Python applications.
It provides a base class named BaseConstants
which the user can subclass to achieve certain behaviours when accessing the class variables defined in the subclass. It also provides three classes that are meant for type-hinting, Immutable
, Yield
and Cache
.
These three type-hinting classes do the following to the class variable:
Immutable
: The class variable annotated with Immutable
is immutable. Its value cannot be changed, any assignment to the class variable will raise an AttributeError
.
Yield
: The class variable annotated with Yield
will always return/yield a value whenever the class variable is accessed. You can assign a function,
Cache
: The class variable annotated with Cache
will always cache the yielded/returned value from the first call to the function/generator/asynchronous generator (alias: async-gen). Subsequent accesses to the class variable will return the cached value.
Installation
You can use pip to install this package
pip install -U truconsts
Usage
If you want immutable constants
from truconsts.constants import BaseConstants
from truconsts.annotations import Immutable
class MyConstants(BaseConstants):
# annotate with `Immutable`
MyImmutable: Immutable = "Cannot Be Changed"
try:
MyConstants.MyImmutable = "Let's change"
except AttributeError as err:
print(err)
# prints `MyConstants.MyImmutable` cannot be mutated
If you want cached constants
'cached' constants refer to constants which are first 'gotten' through a function call and subsequent use of these constants need not be accessed through that function call.
import time
import datetime
def get_from_network():
time.sleep(2)
return 'Going to cache'
class MyConstants(BaseConstants):
# annotate with `Cache`
MyCache: Cache = get_from_network
start = datetime.datetime.now()
MyConstants.MyCache
end = datetime.datetime.now()
print(f"Time taken to access the variable: {end-start}")
# Time taken to access the variable: 0:00:02.000991
start = datetime.datetime.now()
MyConstants.MyCache
end = datetime.datetime.now()
print(f"Time taken to access the variable after caching: {end-start}")
# Time taken to access the variable after caching: 0:00:00.000999
If you want 'yielding' constants
'yielding' constants refer to constants (which are not 'really' constants in the strictest sense, but it's Python yeah...) to always generate a new value whenever you access them.
import random
def gen():
while True: # this while loop is import
# if you always want a random number
# to be generate from this generator
num = random.randint(0, 100)
yield num
class MyConstants(BaseConstants):
# annotate with `Yield`
RANDOM_INT: Yield = gen
print(MyConstants.RANDOM_INT) # 23
print(MyConstants.RANDOM_INT) # 88
If you want 'yielding' constants from an asynchronous generator
Same as the above, but now with asynchronous generator. It makes your generators run as if they are synchronous.
async def gen():
i = 1
while i:
yield i
i += 1
async def getter():
async_asend_gen = gen()
while True:
num = await async_asend_gen.asend(None)
yield num
class MyConstants(BaseConstants):
COUNT_UP: Yield = getter()
print(MyConstants.COUNT_UP) # 1
print(MyConstants.COUNT_UP) # 2
print(MyConstants.COUNT_UP) # 3
print(MyConstants.COUNT_UP) # 4
If you want a mix of constants
# Simple API, just subclass `BaseConstants`
class Constants(BaseConstants):
# `NUM` is an immutable `int`, i.e. Constants.NUM will always be 123
NUM: Immutable[int] = 123
# No `Immutable` annotation implies Constants.STR is mutable
STR: str = "Hello"
# Constants.IMMU_FUNC will call `get_constant` function; the returned value is cached
# and it is immutable
IMMU_FUNC: Cache[Immutable] = get_constant
# Order/Subscripting of annotation does not matter
MUT_FUNC: Immutable[Cache] = get_constant
# Only `Cache` annotation without `Immutable` means it is mutable even after
# the returned value is cached after being called for the first time
JUST_CACHE: Cache[str] = get_constant
# No annotation means it is neither `Cache` nor `Immutable`
NO_ANNO = "NO_ANNO"
Finally, if you want to manage your own asynchronous generator but want the 'reference' to it to be immutable
async def gen():
i = 1
while i:
stop = yield i
if stop == True:
print("Someone asked me to stop!")
return
i += 1
async def getter():
async_asend_gen = gen()
num = None
while True:
i = await async_asend_gen.asend(num)
num = yield i
class MyConstants(BaseConstants):
INT: Immutable = getter()
print(await MyConstants.INT.asend(None)) # 1
print(await MyConstants.INT.asend(None)) # 2
print(await MyConstants.INT.asend(None)) # 3
print(await MyConstants.INT.asend(None)) # 4
print(await MyConstants.INT.asend(True)) # Someone asked me to stop!;
# Raises `RuntimeError: async generator raised StopAsyncIteration``
There are more examples in the examples
folder on Github.
Roadmap
Description | Progress | Code Sample |
---|---|---|
Subclassing e.g. Immutables make all subclass' class variables immutable |
[1] | |
Able to define inner class in outer class definition and declare annotation through parameters passed into class call | [1] |
Samples
[1]
# Future APIs
class MyConstants(BaseConstants):
class FilePaths(Immutables, this_class_as=(Immutable,)):
# All `TRAINING`, `TESTING` class variables will be `Immutable`.
# The class variable `FilePaths` of `MyConstants`
# will be immutable as well.
TRAINING = "."
TESTING = ".."
VALIDATION = "..."
class Yielders(Yields):
# Same as above just that all class variables will be
# `Yield` annotated but `Yielders` will be mutable
FIRST = gen
Contributing
Contributions are welcome!
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.