Package: coppyr
Coppyr (Copp-er) is a collecton of useful Python boilerplate that I find
myself reusing frequently between projects.subpsingletonSingletonNamespaceContextlazypropertyCoppyrErrorsubpsubp.callConvenience wrapper aroundsubprocess.runthat abstracts many of the
common options and features (such assubprocess.PIPEpassing).>>> from coppyr import subp
>>> retcode, stdout, stederr = subp.call("lsb_release -a")
>>> print retcode
0
>>> print stdout
['Distributor ID:\tUbuntu', 'Description:\tUbuntu 18.04.3 LTS',
'Release:\t18.04', 'Codename:\tbionic', '']
>>> print stderr
['No LSB modules are available.', '']Note:STDOUTandSTDERRare returned asListobjects with each
line as aString.  This includes empty lines which become empty strings.singletonsingleton.SingletonBase object that implements the Singleton pattern pythonically.  Future inits
of this object will return previously the first created object.>>> from coppyr.types import Singleton
>>> first = Singleton()
>>> first
<singleton.Singleton object at 0x7fa72df4cd30>
>>> second = Singleton()
>>> second
<singleton.Singleton object at 0x7fa72df4cd30>This object can be used as a base class or mixin to add Singleton behavior to
custom objects.Warning:When inheriting from Singleton it is neccessary to override the_instanceclass attribute to ensure that you don’t inadvertantly store your
subclass instance in the parent class variable
(types.Singleton._instance).  For the same reason, you should also
override_initas well.class MySingletonClass(Singleton):
    _instance = None
    _init = Falsesingleton.NamespaceSimple Singleton object that stores KV pairs.>>> from coppyr.singleton import Namespace
>>> ns = Namespace()
>>> ns.foo = "bar"
>>> ns.foo
'bar'
>>> ns2 = Namespace()
>>> ns2.foo
'bar'ReturnsNoneif the key is not in the namespace.>>> ns.baz
>>>Warning:Just likeSingleton, child objects should override the
class_instanceand_initattributes.__getattr__(self, attr)When an attribute does not exist, aNamespacewill returnNoneinstead of raising anAttributeError.ContextContextThis is intended as an interpreter local object that can store common state
between executing threads/coroutines.  It’s a convenient tool to provide
access to shared utilities such as logging, environment information, and
other shared utilities for an application.>>> from coppyr import Context
>>> context = Context()
>>> context.action_id
'15_100000'
>>> context.inc_action_id()
>>> context.action_id
'15_100001'lazypropertylazypropertyThis is a decorator that will turn a class method into a property that is
evaluated once.  This is a useful performance optimization for class elements
that require computation but do not change overtime.>>> from coppyr import lazyproperty
>>> class Foo:
...     def __init__(self):
...         self.a = 5
...         self.b = 6
...
...     @lazyproperty
...     def c(self):
...         return self.a + self.b
...
>>> x = Foo()
>>> x.c
11
>>> x.a = 6
>>> x.c
11  # c remains 11CoppyrErrorCoppyrErrorSimple boilerplate for readable, consistent, custom error messages.  Adds adictrepresentation that can be used for easy(ish) conversion to JSON for
web use cases.>>> from coppyr import CoppyrError
>>> class MyError(CoppyrError):
...     description = "Doom 2: Hell on earth."
...
>>> err = MyError()
>>> raise err
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
__main__.MyError: Doom 2: Hell on earth.
>>> err
MyError(message=Doom 2: Hell on earth., payload={})
>>> err.to_dict()
{'error': 'MyError', 'message': 'Doom 2: Hell on earth.', 'payload': {}}