Skip to main content

keyed-classes

Create pseudo-singleton key based objects like those generated by logging.getLogger

>>> from keyed_classes import KeyedClass
>>> class MyClass(KeyedClass)
...     def __init__(self, key):
...         self.key = key
...
>>> instance_one = MyClass('this is a key')
>>> instance_two = MyClass('this is a key')
>>> instance_three = MyClass('this is a different key')
>>> instance_one is instance_two
True
>>> instance_one is instance_three
False

Note: Some thought needs to be put into the __init__ method of a KeyedClass. If attempting to create a new instance may or may not just return a previously created instance instead, what does that mean for code in __init__, and instance variables (and whatever else) created there-in?

This is getting a bit implementation detail-y, but in every time you try to create a new instance the code in __init__ will be run, self either referring to the newly created instance if the key did not previously exist, and referring to the original instance created from the key if it has been used before.


If you'd like to avoid subclassing KeyedClass but still want something like this for whatever reason, there is also a metaclass version keyed_classes.KeyedClassMeta, but I would recommend against using it, as it's not quite as friendly as keyed_classes.KeyedClass.

>>> from keyed_classes import KeyedClassMeta
>>> class MyClass(metaclass=KeyedClassMeta)
...     def __init__(self, key):
...         self.key = key
...
>>> instance_one = MyClass('this is a key')
>>> instance_two = MyClass('this is a key')
>>> instance_three = MyClass('this is a different key')
>>> instance_one is instance_two
True
>>> instance_one is instance_three
False

Note: The behavior is not exactly the same between the two implementations. keyed_classes.KeyedClassMeta classes actually do create a new instance every time one is requested (and the __init__ method is run on this new instance), but this object is essentially just thrown away before it gets back to the user and the originally created object is returned back to the user.

Why do I want this?

You probably don't!

Generally this is a bit of a cludgy solution, it is effectivly just cleverly using (and hiding from the user) global state, which we all know is something approximating the root of all evil.

I came up with this as a solution to the issue of mutually exclusive groups of options in Click, which does not support that feature itself.

import click
from keyed_classes import KeyedClass

class MutuallyExclusiveOptionGroup(KeyedClass):
    def __init__(self, key):
        self.key = key
        self.tripped = False

    def __call__(self, ctx, param, value):
        if value is None:
            return

        if self.tripped:
            op, _ = self.option
            raise click.BadParameter(f"'{op.name}' already specified, only one '{self.key}' option allowed in one invocation.")
        else:
            self.tripped = True
            self.option = (param, value)
        return value


@click.command()
@click.option("--op1", callback=MutuallyExclusiveOptionGroup('method'))
@click.option("--op2", callback=MutuallyExclusiveOptionGroup('method'))
...
def main(op1, op2, ...):
    ...

Metadata

Release files for keyed-classes 0.1.0

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

Source distribution (sdist)

Source distribution for keyed-classes 0.1.0
File Size Uploaded
keyed-classes-0.1.0.tar.gz 2.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for keyed-classes 0.1.0
File Interpreter ABI Platform
keyed_classes-0.1.0-py2.py3-none-any.whl Python 3, Python 2 none any Details

Total release size: 5.5 kB

Release files / keyed-classes-0.1.0.tar.gz

Download URL keyed-classes-0.1.0.tar.gz
Size 2.6 kB
Tags Source
SHA-256 checksum
How to use checksums
777e309bc74c2b82bf532bb6713d73874f896ecfa84181f5aec925b688326efc
BLAKE2b-256 checksum
How to use checksums
2960b02f0b21cfd2dfb13299c1f86f893e97ed04237793765487ac0af967544f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/0.12.4 CPython/3.7.1 Linux/4.14.78-1-MANJARO

Release files / keyed_classes-0.1.0-py2.py3-none-any.whl

Download URL keyed_classes-0.1.0-py2.py3-none-any.whl
Size 2.9 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
25fe8944f7b2a168ed53617491db4dadef97634a71b7b463c62dda344a573b3a
BLAKE2b-256 checksum
How to use checksums
7b2c50ce24714067c7153cfd7a50f06ea195dc2bd850f9c1d1acc773decc4080
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/0.12.4 CPython/3.7.1 Linux/4.14.78-1-MANJARO

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

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