Convenience facilities for objects.
Project description
Convenience facilities for objects.
Latest release 20260526: Refreshable mixin class embodying refresh logic.
Short summary:
as_dict: Return a dictionary with keys mapping to the values of the attributes ofo.copy: Convenient function to shallow copy an object with simple modifications.flavour: 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.O: TheOclass is now obsolete, please subclasstypes.SimpleNamespaceor use a dataclass.O_attritems: Generator yielding(attr,value)for relevant attributes ofo.O_attrs: Yield attribute names fromowhich are pertinent toO_str.O_merge: Merge key:value pairs from a mapping into an object.O_str: Return astrrepresentation of the objecto.obj_as_dict: OBSOLETE version of obj_as_dict, suggestion: use cs.obj.as_dict.Proxy: An extremely simple proxy object that passes all unmatched attribute accesses to the proxied object.public_subclasses: Return a set of the subclasses ofclswhich have public names.Refreshable: A mixin for refreshable objects. The object must provide a_refresh(resource)method which tries to refresh fromresource.Sentinel: A simple class for named sentinels whosestr()is just the name and whose==usesis.singleton: Obtain an object forkeyviaregistry(a mapping ofkey=>object). Return(is_new,object).SingletonMixin: A mixin turning a subclass into a singleton factory.TrackedClassMixin: A mixin to track all instances of a particular class.
Module contents:
-
as_dict(o, selector=None): Return a dictionary with keys mapping to the values of the attributes ofo.Parameters:
o: the object to mapselector: the optional selection criterion
If
selectoris omitted orNone, select "public" attributes, those not commencing with an underscore.If
selectoris astr, select attributes starting withselector.Otherwise presume
selectoris callable and select attributesattrwhereselector(attr)is true. -
copy(obj, **kw): Convenient function to shallow copy an object with simple modifications.Performs a shallow copy of
selfusingcopy.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): TheOclass is now obsolete, please subclasstypes.SimpleNamespaceor use a dataclass. -
O_attritems(o): Generator yielding(attr,value)for relevant attributes ofo. -
O_attrs(o): Yield attribute names fromowhich are pertinent toO_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 astrrepresentation of the objecto.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 version of obj_as_dict, suggestion: use cs.obj.as_dictOBSOLETE convesion of an object to a
dict. Please uscs.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 ofclswhich have public names. -
class Refreshable: A mixin for refreshable objects. The object must provide a_refresh(resource)method which tries to refresh fromresource.This mixin provides a
.refresh()method which implements the refresh policy.
Refreshable.refresh(self, resource: Optional = None, *, force=False, lifespan: float = None, ratelimit: float = None, recurse=False, seen=None, **_refresh_kw) -> bool:
Refresh this object; if it is stale attempt to refresh via self._refresh().
Return True if the object was updated, False otherwise.
The refresh policy is: if force or (the object's information
is stale and the rate limit does not preclude a refresh),
call self._refresh(resource).
This is measured by self.refresh_needed().
State about the refresh poll times is kept in
self.refresh_last_poll and self.refresh_last_update.
Parameters:
resource: the reference resource, default fromself.refresh_resourceforce: optional flag, defaultFalse; if true attempt a refresh regardless of staleness or the rate limitlifespan: how many seconds before updated information is considered no stale, default fromself.refresh_lifespan, ortype(self).REFRESH_RATELIMITratelimit: how many seconds should elapsed before attempting a refresh, default fromself.refresh_ratelimitortype(self).REFRESH_RATELIMITrecurse: optional flag, defaultFalse; if true the recursively refresh the objects fromself.refresh_related()seen: optional set of keys to prevent unbound recursion Other keyword parameters are passed toself._refresh()if it is called.
Refreshable.refresh_key(self):
Return the key value for the seen set used in a recursive refresh.
This default returns id(self); classes like HasTags
would use a characteristic value like self.name.
Refreshable.refresh_needed(self, *, lifespan: float = None, now: float = None) -> bool:
Test whether self is considered stale.
Parameters:
lifespan: how many seconds before updated information is considered no stale, default fromself.refresh_lifespan, ortype(self).REFRESH_LIFESPANnow: optional reference time, default fromtime.time()
Refreshable.refresh_related(self):
Return the related objects which should also be refreshed in recursive refreshes.
Refreshable.refreshed(self, now: float = None):
Mark self as refreshed as of now, default time.time().
-
class Sentinel: A simple class for named sentinels whosestr()is just the name and whose==usesis.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 forkeyviaregistry(a mapping ofkey=>object). Return(is_new,object).If the
keyexists in the registry, return the associated object. Otherwise create a new object by callingfactory(*fargs,**fkwargs)and store it askeyin theregistry.The
registrymay be any mapping ofkeys to objects but will usually be aweakref.WeakValueDictionaryin 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
SingletonMixinclass 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 = yNote: 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 usingclsinstead ofself. - 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 ... - provide a method
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 indexkey: 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_trackis typically the class name itself, nottype(self)which would track the specific subclass. At some relevant point one can call:self.tcm_dump(class_to_track[, file])class_to_trackneeds atcm_get_statemethod 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 20260526: Refreshable mixin class embodying refresh logic.
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
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.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cs_obj-20260526.tar.gz.
File metadata
- Download URL: cs_obj-20260526.tar.gz
- Upload date:
- Size: 12.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9159ee1b545f62a7335a5a8e290a7909311ee6f3c33263865934c59d0cffdf9a
|
|
| MD5 |
fe5804e370c6d8cf01cab3091d2ab9b1
|
|
| BLAKE2b-256 |
c061b142d59e43b7fc7f957bc3db9680153d91926791c94e4845f1efad5f0d6e
|
File details
Details for the file cs_obj-20260526-py2.py3-none-any.whl.
File metadata
- Download URL: cs_obj-20260526-py2.py3-none-any.whl
- Upload date:
- Size: 13.0 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3f18c010abdb8f9a10c79f526069ce2945c6d4af75818b9a90fa8eb4a729986e
|
|
| MD5 |
32aecdcbe5dd91f569c4517fa2aba3ff
|
|
| BLAKE2b-256 |
ae2edd19146c0135e72a73b0c2aa13f54536fe4b514dbc87326fbf49743a005e
|