Skip to main content

Constants collections without hassle

Project description

short-con: Constants collections without hassle

Motivation

When your Python code needs constants, the process often starts simply enough with the worthy goal of getting the magic strings and numbers out of your code.

BLACK = 'black'
WHITE = 'white'

KING = 0
QUEEN = 9
ROOK = 5
BISHOP = 3
KNIGHT = 3
PAWN = 1

At some point, you might need to operate on those constants in groups, so you add some derived constants. We've hardly gotten out of the gate and the journey already seems tedious.

COLORS = (BLACK, WHITE)
PIECES = (KING, QUEEN, ROOK, BISHOP, KNIGHT, PAWN)

Starting in Python 3.4, the enum library became available:

from enum import Enum

Colors = Enum('Colors', 'BLACK WHITE')
Pieces = Enum('Pieces', dict(KING = 0, QUEEN = 9, ROOK = 5, BISHOP = 3, KNIGHT = 3, PAWN = 1))

Although that library helps a lot, there is one annoyance. We started with the simple goal of wrangling magic strings and values, but we end up forced to interact with special enum instances:

Pieces.QUEEN        # Will this give us the value we want? No.
Pieces.QUEEN.value  # Dig a level deeper, friend.

Although there are use cases where such formalism might be desirable, in the vast majority of practical programming situations the intermediate object is just a hassle — a form of robustness theater rather than an actual best practice with concrete benefits.

An easier way

The short-con project simplifies the creation of constants collections: just supply names and values via keyword arguments.

from short_con import cons

PIECES = cons(king = 0, queen = 9, rook = 5, bishop = 3, knight = 3, pawn = 1)

Behind the scenes cons() defines a frozen dataclass and then returns an instance of that class.

Pieces.queen = 99   # Fails with FrozenInstanceError.

The underlying values are directly accessible — no need to interact with a bureaucratic object standing guard in the middle:

PIECES.queen == 9  # True

The object is directly iterable and convertible to other collections, in the manner of dict.items():

for name, value in PIECES:
    print(name, value)

d = dict(PIECES)
tups = list(PIECES)

The object also supports relevant read-only dict behaviors:

# Always supported.
PIECES['queen']      # 9
len(PIECES)          # 6
'queen' in PIECES    # True

# Supported if the attribute names do not conflict with the method names.
PIECES.keys()        # ('king', 'queen', 'rook', 'bishop', 'knight', 'pawn')
PIECES.values()      # (0, 9, 5, 3, 3, 1)
PIECES.get('rook')   # 5
PIECES.get('blort')  # None

For situations when the values are the same as the attribute names, usage is even more compact: just supply names as positional arguments or via one or more space-delimited strings.

COLORS = cons('black white')
COLORS = cons('black', 'white')

print(COLORS)  # ShortCon(black='black', white='white')

Easier enums

In the same spirit of reducing hassle, the library supports the creation of enum-like collections: supply the names and, optionally, start and step parameters to control the generation of the numeric values.

PETS1 = enumcons('dog cat parrot')
PETS2 = enumcons('dog cat parrot', start = 100, step = -10)

print(PETS1)  # ShortCon(dog=1, cat=2, parrot=3)
print(PETS2)  # ShortCon(dog=100, cat=90, parrot=80)

More control when needed

The library also provides a constants() function that supports (1) the ability to control the class name of the underlying dataclass, (2) use cases where the constant values can be computed from the names, and (3) the ability to control whether the dataclass is frozen (default is true).

COLORS = constants(
    'black white',         # Names/values (dict) or names (list, tuple, str)
    cls_name = 'Colors',
    val_func = str.upper,  # Callable: f(NAME) => VALUE
    frozen = False,
)

COLORS.black += '_'
print(COLORS)  # Colors(black='BLACK_', white='WHITE')

Quick and dirty dataclasses

Since we are in the business of making dataclasses, the library also provides a convenience function to create them with a simplicity analogous to the cons() function. The user provides the attributes names and, optionally, a class name or any other keyword arguments for dataclasses.make_dataclass(). The attributes of the returned dataclass are optional, with a default of None, and have a type of typing.Any.

Person = dc('name age hobby')
p = Person(name = 'Billy', age = 42)
print(p)  # ShortCon(name='Billy', age=42, hobby=None)

Soldier = dc('name', 'rank', 'serial', cls_name = 'Soldier', frozen = True)
s = Soldier(name = 'Leonard', rank = 'Private')
print(s)  # Soldier(name='Leonard', rank='Private', serial=None)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

short-con-2.1.0.tar.gz (8.5 kB view details)

Uploaded Source

Built Distribution

short_con-2.1.0-py3-none-any.whl (6.6 kB view details)

Uploaded Python 3

File details

Details for the file short-con-2.1.0.tar.gz.

File metadata

  • Download URL: short-con-2.1.0.tar.gz
  • Upload date:
  • Size: 8.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.9.4

File hashes

Hashes for short-con-2.1.0.tar.gz
Algorithm Hash digest
SHA256 531e8763ebbbdaf338b8653bb007c889142434001d08544e542c6e6648b28245
MD5 eb58d5cfa32ac2ae5472ea0d6999d5b1
BLAKE2b-256 014a662cd76da3fbf2fc95a90b4e9fc37720bbb6f324d464e655e23a5e2710d0

See more details on using hashes here.

File details

Details for the file short_con-2.1.0-py3-none-any.whl.

File metadata

  • Download URL: short_con-2.1.0-py3-none-any.whl
  • Upload date:
  • Size: 6.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.9.4

File hashes

Hashes for short_con-2.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f66263ffc276d00b452b0dd4561ca55599cd390b7eb0636e548491b1ebcdc3bf
MD5 551b2acfe47ec101f30686245d74576e
BLAKE2b-256 4eb8caf9f5f485f778384a3d97b9b348e1d84e29882edb9fe189391d033de0da

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page