Skip to main content

truconsts

Actions Coverage License PyPI Wheel Python Versions Python Implementations Source Mirror Issues Docs Changelog Downloads


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!

Release files for truconsts 0.0.9

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for truconsts 0.0.9
File Size Uploaded
truconsts-0.0.9.tar.gz 53.8 kB Details

Release files / truconsts-0.0.9.tar.gz

Download URL truconsts-0.0.9.tar.gz
Size 53.8 kB
Tags Source
SHA-256 checksum
How to use checksums
dace782b928ba69e4a6c358dff71eede396f373afad05cb322d30d29904133ba
BLAKE2b-256 checksum
How to use checksums
158e793a0bff4b805f26c327a799b3f647ffb41467c8c24323ae78b513a5b809
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.2 CPython/3.10.6

Release history Release notifications | RSS feed

This release

0.0.9 This release

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page