Skip to main content

Convenience facilities for objects.

Project description

Convenience facilities for objects.

Latest release 20250306:

  • Remove cs.py3 dependency, this module has not worked in python2 for quite a while.
  • copy: drop use of positional parameters.

as_dict(o, selector=None)

Return a dictionary with keys mapping to the values of the attributes of o.

Parameters:

  • o: the object to map
  • selector: the optional selection criterion

If selector is omitted or None, select "public" attributes, those not commencing with an underscore.

If selector is a str, select attributes starting with selector.

Otherwise presume selector is callable and select attributes attr where selector(attr) is true.

copy(obj, **kw)

Convenient function to shallow copy an object with simple modifications.

Performs a shallow copy of self using copy.copy.

Treat all keyword arguments as (attribute,value) 2-tuples and replace those attributes with the supplied values.

flavour(obj)

Return constants indicating the ``flavour'' of an object:

  • T_MAP: DictType, DictionaryType, objects with an keys or keys attribute.
  • T_SEQ: TupleType, ListType, objects with an iter attribute.
  • T_SCALAR: Anything else.

Class O(types.SimpleNamespace)

The O class is now obsolete, please subclass types.SimpleNamespace or use a dataclass.

O_attritems(o)

Generator yielding (attr,value) for relevant attributes of o.

O_attrs(o)

Yield attribute names from o which are pertinent to O_str.

Note: this calls getattr(o,attr) to inspect it in order to prune callables.

O_merge(o, _conflict=None, _overwrite=False, **kw)

Merge key:value pairs from a mapping into an object.

Ignore keys that do not start with a letter. New attributes or attributes whose values compare equal are merged in. Unequal values are passed to:

_conflict(o, attr, old_value, new_value)

to resolve the conflict. If _conflict is omitted or None then the new value overwrites the old if _overwrite is true.

O_str(o, no_recurse=False, seen=None)

Return a str representation of the object o.

Parameters:

  • o: the object to describe.
  • no_recurse: if true, do not recurse into the object's structure. Default: False.
  • seen: a set of previously sighted objects to prevent recursion loops.

obj_as_dict(o, **kw)

OBSOLETE obj_as_dict

OBSOLETE convesion of an object to a dict. Please us cs.obj.as_dict.

Class Proxy

An extremely simple proxy object that passes all unmatched attribute accesses to the proxied object.

Note that setattr and delattr work directly on the proxy, not the proxied object.

public_subclasses(cls, extras=())

Return a set of the subclasses of cls which have public names.

Class Sentinel

A simple class for named sentinels whose str() is just the name and whose == uses is.

Example:

>>> from cs.obj import Sentinel
>>> MISSING = Sentinel("MISSING")
>>> print(MISSING)
MISSING
>>> other = Sentinel("other")
>>> MISSING == other
False
>>> MISSING == MISSING
True

singleton(registry, key, factory, fargs, fkwargs)

Obtain an object for key via registry (a mapping of key=>object). Return (is_new,object).

If the key exists in the registry, return the associated object. Otherwise create a new object by calling factory(*fargs,**fkwargs) and store it as key in the registry.

The registry may be any mapping of keys to objects but will usually be a weakref.WeakValueDictionary in order that object references expire as normal, allowing garbage collection.

Note: this function is not thread safe. Multithreaded users should hold a mutex.

See the SingletonMixin class for a simple mixin to create singleton classes, which does provide thread safe operations.

Class SingletonMixin

A mixin turning a subclass into a singleton factory.

Note: this mixin overrides object.__new__ and may not play well with other classes which override __new__.

Warning: because of the mechanics of __new__, the instance's __init__ method will always be called after __new__, even when a preexisting object is returned. Therefore that method should be sensible even for an already initialised and probably subsequently modified object.

My suggested approach is to access some attribute, and preemptively return if it already exists. Example:

def __init__(self, x, y):
    if 'x' in self.__dict__:
        return
    self.x = x
    self.y = y

Note: we probe self.__dict__ above to accomodate classes with a __getattr__ method.

Note: each class registry has a lock, which ensures that reuse of an object in multiple threads will call the __init__ method in a thread safe serialised fashion.

Implementation requirements: a subclass should:

  • provide a method _singleton_key(*args,**kwargs) returning a key for use in the single registry, computed from the positional and keyword arguments supplied on instance creation i.e. those which __init__ would normally receive. This should have the same signature as __init__ but using cls instead of self.
  • provide a normal __init__ method which can be safely called again after some earlier initialisation.

This class is thread safe for the registry operations.

Example:

class Pool(SingletonMixin):

    @classmethod
    def _singleton_key(cls, foo, bah=3):
        return foo, bah

    def __init__(self, foo, bah=3):
        if hasattr(self, 'foo'):
            return
       ... normal __init__ stuff here ...
       self.foo = foo
       ...

SingletonMixin.__hash__(self): default hash and equality methods

SingletonMixin.singleton_also_by(also_key, key): Obtain a singleton by a secondary key. Return the instance or None.

Parameters:

  • also_key: the name of the secondary key index
  • key: the key for the index

Class TrackedClassMixin

A mixin to track all instances of a particular class.

This is aimed at checking the global state of objects of a particular type, particularly states like counters. The tracking is attached to the class itself.

The class to be tracked includes this mixin as a superclass and calls:

TrackedClassMixin.__init__(class_to_track)

from its init method. Note that class_to_track is typically the class name itself, not type(self) which would track the specific subclass. At some relevant point one can call:

self.tcm_dump(class_to_track[, file])

class_to_track needs a tcm_get_state method to return the salient information, such as this from cs.resources.MultiOpenMixin:

def tcm_get_state(self):
    return {'opened': self.opened, 'opens': self._opens}

See cs.resources.MultiOpenMixin for example use.

TrackedClassMixin.tcm_all_state(klass): Generator yielding tracking information for objects of type klass in the form (o,state) where o if a tracked object and state is the object's get_tcm_state method result.

TrackedClassMixin.tcm_dump(klass, f=None): Dump the tracking information for klass to the file f (default sys.stderr).

Release Log

Release 20250306:

  • Remove cs.py3 dependency, this module has not worked in python2 for quite a while.
  • copy: drop use of positional parameters.

Release 20250103: public_subclasses: new optional extras= parameter for additional classes to scan, now returns a set.

Release 20241009: public_subclasses: catch TypeError from "type.subclasses", which is just a function.

Release 20241005: New public_subclasses(cls) returning all subclasses with public names.

Release 20220918:

  • SingletonMixin: change example to probe self__dict__ instead of hasattr, faster and less fragile.
  • New Sentinel class for named sentinel objects, equal only to their own instance.

Release 20220530: SingletonMixin: add default hash and eq methods to support dict and set membership.

Release 20210717: SingletonMixin: if cls._singleton_key returns None we always make a new instance and do not register it.

Release 20210306: SingletonMixin: make singleton_also_by() a public method.

Release 20210131: SingletonMixin: new _singleton_also_indexmap method to return a mapping of secondary keys to values to secondary lookup, _singleton_also_index() to update these indices, _singleton_also_by to look up a secondary index.

Release 20210122: SingletonMixin: new _singleton_instances() method returning a list of the current instances.

Release 20201227: SingletonMixin: correctly invoke new, a surprisingly fiddly task to get right.

Release 20201021:

  • @OBSOLETE(obj_as_dict), recommend "as_dict()".
  • [BREAKING] change as_dict() to accept a single optional selector instead of various mutually exclusive keywords.

Release 20200716: SingletonMixin: no longer require special _singleton_init method, reuse default init implicitly through new mechanics.

Release 20200517: Documentation improvements.

Release 20200318:

  • Replace obsolete O class with a new subclass of SimpleNamespace which issues a warning.
  • New singleton() generic factory function and SingletonMixin mixin class for making singleton classes.

Release 20190103:

  • New mixin class TrackedClassMixin to track all instances of a particular class.
  • Documentation updates.

Release 20170904: Minor cleanups.

Release 20160828:

  • Use "install_requires" instead of "requires" in DISTINFO.
  • Minor tweaks.

Release 20150118: move long_description into cs/README-obj.rst

Release 20150110: cleaned out some old junk, readied metadata for PyPI

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

cs_obj-20250306.tar.gz (8.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cs_obj-20250306-py2.py3-none-any.whl (10.7 kB view details)

Uploaded Python 2Python 3

File details

Details for the file cs_obj-20250306.tar.gz.

File metadata

  • Download URL: cs_obj-20250306.tar.gz
  • Upload date:
  • Size: 8.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.7

File hashes

Hashes for cs_obj-20250306.tar.gz
Algorithm Hash digest
SHA256 26e907266082789d9b8868c2954e2d5015967a102ffe915a5be80c71a94cf642
MD5 837283c76159e60f3a5345dacbd254a9
BLAKE2b-256 eb62a1d2c8547f94acf7d57fba5ba46b901fa05cffc368ddc25c07a7dbfe1ca6

See more details on using hashes here.

File details

Details for the file cs_obj-20250306-py2.py3-none-any.whl.

File metadata

  • Download URL: cs_obj-20250306-py2.py3-none-any.whl
  • Upload date:
  • Size: 10.7 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.7

File hashes

Hashes for cs_obj-20250306-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 f358ed3bd1dcd69102dd2bd0117368efe3f24332140b9214cf74d749f26af456
MD5 290d7d9eb5295bc871d8882998002f6d
BLAKE2b-256 ff233bf06665e813073ed875077a3a066b352afa40d88ef22d9903adc76e331f

See more details on using hashes here.

Supported by

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