Documentation for property-manager¶
Welcome to the documentation of property-manager version 3.0! The following sections are available:
User documentation¶
The readme is the best place to start reading and provides examples:
property-manager: Useful property variants for Python programming¶
The property-manager package defines several custom property variants for Python programming including required properties, writable properties, cached properties, etc. It’s currently tested on Python 2.7, 3.5, 3.6, 3.7, 3.8 and PyPy. For usage instructions please refer to the documentation.
Status¶
The property-manager package came into existence as a submodule of my executor package where I wanted to define classes with a lot of properties that had a default value which was computed on demand but also needed to support assignment to easily override the default value.
Since I created that module I’d wanted to re-use it in a couple of other projects I was working on, but adding an executor dependency just for the property_manager submodule felt kind of ugly.
This is when I decided that it was time for the property-manager package to be created. When I extracted the submodule from executor I significantly changed its implementation (making the code more robust and flexible) and improved the tests, documentation and coverage in the process.
Installation¶
The property-manager package is available on PyPI which means installation should be as simple as:
$ pip install property-manager
There’s actually a multitude of ways to install Python packages (e.g. the per user site-packages directory, virtual environments or just installing system wide) and I have no intention of getting into that discussion here, so if this intimidates you then read up on your options before returning to these instructions ;-).
Usage¶
This section shows how to use the most useful property subclasses. Please refer to the documentation for more detailed information.
Writable properties¶
Writable properties with a computed default value are easy to create using the writable_property decorator:
from random import random
from property_manager import writable_property
class WritablePropertyDemo(object):
@writable_property
def change_me(self):
return random()
First let’s see how the computed default value behaves:
>>> instance = WritablePropertyDemo()
>>> print(instance.change_me)
0.13692489329941815
>>> print(instance.change_me)
0.8664002331885933
As you can see the value is recomputed each time. Now we’ll assign it a value:
>>> instance.change_me = 42
>>> print(instance.change_me)
42
From this point onwards change_me will be the number 42 and it’s impossible to revert back to the computed value:
>>> delattr(instance, 'change_me')
Traceback (most recent call last):
File "property_manager/__init__.py", line 584, in __delete__
raise AttributeError(msg % (obj.__class__.__name__, self.__name__))
AttributeError: 'WritablePropertyDemo' object attribute 'change_me' is read-only
If you’re looking for a property that supports both assignment and deletion (clearing the assigned value) you can use mutable_property.
Required properties¶
The required_property decorator can be used to create required properties:
from property_manager import PropertyManager, required_property
class RequiredPropertyDemo(PropertyManager):
@required_property
def important(self):
"""A very important attribute."""
What does it mean for a property to be required? Let’s create an instance of the class and find out:
>>> instance = RequiredPropertyDemo()
Traceback (most recent call last):
File "property_manager/__init__.py", line 131, in __init__
raise TypeError("%s (%s)" % (msg, concatenate(missing_properties)))
TypeError: missing 1 required argument (important)
So the constructor of the class raises an exception when the property hasn’t been given a value. We can give the property a value by providing keyword arguments to the constructor:
>>> instance = RequiredPropertyDemo(important=42)
>>> print(instance)
RequiredPropertyDemo(important=42)
We can also assign a new value to the property:
>>> instance.important = 13
>>> print(instance)
RequiredPropertyDemo(important=13)
Cached properties¶
Two kinds of cached properties are supported, we’ll show both here:
from random import random
from property_manager import cached_property, lazy_property
class CachedPropertyDemo(object):
@cached_property
def expensive(self):
print("Calculating expensive property ..")
return random()
@lazy_property
def non_idempotent(self):
print("Calculating non-idempotent property ..")
return random()
The properties created by the cached_property decorator compute the property’s value on demand and cache the result:
>>> instance = CachedPropertyDemo()
>>> print(instance.expensive)
Calculating expensive property ..
0.763863180683
>>> print(instance.expensive)
0.763863180683
The property’s cached value can be invalidated in order to recompute its value:
>>> del instance.expensive
>>> print(instance.expensive)
Calculating expensive property ..
0.396322737214
>>> print(instance.expensive)
0.396322737214
Now that you understand cached_property, explaining lazy_property is very simple: It simply doesn’t support invalidation of cached values! Here’s how that works in practice:
>>> instance.non_idempotent
Calculating non-idempotent property ..
0.27632566561900895
>>> instance.non_idempotent
0.27632566561900895
>>> del instance.non_idempotent
Traceback (most recent call last):
File "property_manager/__init__.py", line 499, in __delete__
raise AttributeError(msg % (obj.__class__.__name__, self.__name__))
AttributeError: 'CachedPropertyDemo' object attribute 'non_idempotent' is read-only
>>> instance.non_idempotent
0.27632566561900895
Properties based on environment variables¶
The constructor of the custom_property class (and its subclasses) accepts the keyword argument environment_variable which can be provided to get the property’s value from the environment:
from random import random
from property_manager import mutable_property
class EnvironmentPropertyDemo(object):
@mutable_property(environment_variable='WHATEVER_YOU_WANT')
def environment_based(self):
return 'some-default-value'
By default the property’s value is computed as expected:
>>> instance = EnvironmentPropertyDemo()
>>> print(instance.environment_based)
some-default-value
When the environment variable is set it overrides the computed value:
>>> os.environ['WHATEVER_YOU_WANT'] = '42'
>>> print(instance.environment_based)
42
Assigning a value to the property overrides the value from the environment:
>>> instance.environment_based = '13'
>>> print(instance.environment_based)
13
Deleting the property clears the assigned value so that the property falls back to the environment:
>>> delattr(instance, 'environment_based')
>>> print(instance.environment_based)
42
If we now clear the environment variable as well then the property falls back to the computed value:
>>> os.environ.pop('WHATEVER_YOU_WANT')
'42'
>>> print(instance.environment_based)
some-default-value
Support for setters and deleters¶
All of the custom property classes support setters and deleters just like
Python’s property
decorator does.
The PropertyManager class¶
When you define a class that inherits from the PropertyManager class the following behavior is made available to your class:
- Required properties raise an exception if they’re not set.
- The values of writable properties can be set by passing keyword arguments to the constructor of your class.
- The repr() of your objects will render the name of the class and the names and values of all properties. Individual properties can easily be excluded from the repr() output.
- The clear_cached_properties() method can be used to invalidate the cached values of all cached properties at once.
Additionally you can use the property_manager.sphinx module as a Sphinx extension to automatically generate boilerplate documentation that provides an overview of base classes, properties, public methods and special methods.
Similar projects¶
The Python Package Index contains quite a few packages that provide custom properties with similar semantics:
- cached-property
- My personal favorite until I wrote my own :-). This package provides several cached property variants. It supports threading and time based cache invalidation which property-manager doesn’t support.
- lazy-property
- This package provides two cached property variants: a read only property and a writable property. Both variants cache computed values indefinitely.
- memoized-property
- This package provides a single property variant which simply caches computed values indefinitely.
- property-caching
- This package provides several cached property variants supporting class properties, object properties and cache invalidation.
- propertylib
- This package uses metaclasses to implement an alternative syntax for defining computed properties. It defines several property variants with semantics that are similar to those defined by the property-manager package.
- rwproperty
- This package implements computed, writable properties using an alternative syntax to define the properties.
Distinguishing features¶
Despite all of the existing Python packages discussed above I decided to create and publish the property-manager package because it was fun to get to know Python’s descriptor protocol and I had several features in mind I couldn’t find anywhere else:
A superclass that sets writable properties based on constructor arguments.
A superclass that understands required properties and raises a clear exception if a required property is not properly initialized.
Clear disambiguation between lazy properties (whose computed value is cached but cannot be invalidated because it would compromise internal state) and cached properties (whose computed value is cached but can be invalidated to compute a fresh value).
An easy way to quickly invalidate all cached properties of an object.
An easy way to change the semantics of custom properties, e.g. what if the user wants a writable cached property? With property-manager it is trivial to define new property variants by combining existing semantics:
from property_manager import cached_property class WritableCachedPropertyDemo(object): @cached_property(writable=True) def expensive_overridable_attribute(self): """Expensive calculations go here."""
The example above creates a new anonymous class and then immediately uses that to decorate the method. We could have given the class a name though:
from property_manager import cached_property writable_cached_property = cached_property(writable=True) class WritableCachedPropertyDemo(object): @writable_cached_property def expensive_overridable_attribute(self): """Expensive calculations go here."""
By giving the new property variant a name it can be reused. We can go one step further and properly document the new property variant:
from property_manager import cached_property class writable_cached_property(cached_property): """A cached property that supports assignment.""" writable = True class WritableCachedPropertyDemo(object): @writable_cached_property def expensive_overridable_attribute(self): """Expensive calculations go here."""
I’ve used computed properties for years in Python and over those years I’ve learned that different Python projects have different requirements from custom property variants. Defining every possible permutation up front is madness, but I think that the flexibility with which the property-manager package enables adaptation gets a long way. This was the one thing that bothered me the most about all of the other Python packages that implement property variants: They are not easily adapted to unanticipated use cases.
Contact¶
The latest version of property-manager is available on PyPI and GitHub. The documentation is hosted on Read the Docs and includes a changelog. For bug reports please create an issue on GitHub. If you have questions, suggestions, etc. feel free to send me an e-mail at peter@peterodding.com.
API documentation¶
The following API documentation is automatically generated from the source code:
API documentation¶
The following API documentation was automatically generated from the source code of property-manager 3.0:
property_manager
¶
Useful property
variants for Python programming.
Introduction¶
The property_manager
module defines several property
variants
that implement Python’s descriptor protocol to provide decorators that turn
methods into computed properties with several additional features.
Custom property types¶
Here’s an overview of the predefined property variants and their supported operations:
Variant | Assignment | Reassignment | Deletion | Caching |
---|---|---|---|---|
custom_property |
No | No | No | No |
writable_property |
Yes | Yes | No | No |
mutable_property |
Yes | Yes | Yes | No |
required_property |
Yes | Yes | No | No |
key_property |
Yes | No | No | No |
lazy_property |
No | No | No | Yes |
cached_property |
No | No | Yes | Yes |
If you want a different combination of supported options (for example a cached
property that supports assignment) this is also possible, please take a look at
custom_property.__new__()
.
The following inheritance diagram shows how the predefined property
variants relate to each other:

The property manager superclass¶
In addition to these property
variants the property_manager
module also defines a PropertyManager
class which implements several
related enhancements:
- Keyword arguments to the constructor can be used to set writable properties
created using any of the
property
variants defined by theproperty_manager
module. - Required properties without an assigned value will cause the constructor
to raise an appropriate exception (
TypeError
). - The
repr()
ofPropertyManager
objects shows the names and values of all properties. Individual properties can be omitted from therepr()
output by setting therepr
option toFalse
.
Logging¶
The property_manager
module emits log messages at the custom log level
SPAM
which is considered more verbose than DEBUG
, so if you want these messages to be logged make sure they’re not
being ignored based on their level.
Classes¶
-
property_manager.
SPHINX_ACTIVE
= True¶ True
when Sphinx is running,False
otherwise.We detect whether Sphinx is running by checking for the presence of the ‘sphinx’ key in
sys.modules
. The result determines the default value ofUSAGE_NOTES_ENABLED
.
-
property_manager.
USAGE_NOTES_VARIABLE
= 'PROPERTY_MANAGER_USAGE_NOTES'¶ The name of the environment variable that controls whether usage notes are enabled (a string).
-
property_manager.
USAGE_NOTES_ENABLED
= True¶ True
if usage notes are enabled,False
otherwise.This defaults to the environment variable
USAGE_NOTES_VARIABLE
(coerced usingcoerce_boolean()
) when available, otherwiseSPHINX_ACTIVE
determines the default value.Usage notes are only injected when Sphinx is running because of performance. It’s nothing critical of course, but modifying hundreds or thousands of docstrings that no one is going to look at seems rather pointless :-).
-
property_manager.
NOTHING
= <object object>¶ A unique object instance used to detect missing attributes.
-
property_manager.
set_property
(obj, name, value)[source]¶ Set or override the value of a property.
Parameters: - obj – The object that owns the property.
- name – The name of the property (a string).
- value – The new value for the property.
This function directly modifies the
__dict__
of the given object and as such it avoids any interaction with object properties. This is intentional:set_property()
is meant to be used by extensions of the property-manager project and by user defined setter methods.
-
property_manager.
clear_property
(obj, name)[source]¶ Clear the assigned or cached value of a property.
Parameters: - obj – The object that owns the property.
- name – The name of the property (a string).
This function directly modifies the
__dict__
of the given object and as such it avoids any interaction with object properties. This is intentional:clear_property()
is meant to be used by extensions of the property-manager project and by user defined deleter methods.
-
property_manager.
format_property
(obj, name)[source]¶ Format an object property’s dotted name.
Parameters: - obj – The object that owns the property.
- name – The name of the property (a string).
Returns: The dotted path (a string).
-
class
property_manager.
PropertyManager
(**kw)[source]¶ Optional superclass for classes that use the computed properties from this module.
Provides support for required properties, setting of properties in the constructor and generating a useful textual representation of objects with properties.
Here’s an overview of the
PropertyManager
class:Superclass: object
Special methods: __eq__()
,__ge__()
,__gt__()
,__hash__()
,__init__()
,__le__()
,__lt__()
,__ne__()
and__repr__()
Public methods: clear_cached_properties()
,find_properties()
,have_property()
,render_properties()
andset_properties()
Properties: key_properties
,key_values
,missing_properties
,repr_properties
andrequired_properties
-
__init__
(**kw)[source]¶ Initialize a
PropertyManager
object.Parameters: kw – Any keyword arguments are passed on to set_properties()
.
-
set_properties
(**kw)[source]¶ Set instance properties from keyword arguments.
Parameters: kw – Every keyword argument is used to assign a value to the instance property whose name matches the keyword argument. Raises: TypeError
when a keyword argument doesn’t match aproperty
on the given object.
-
key_values
¶ A tuple of tuples with (name, value) pairs for each name in
key_properties
.
-
missing_properties
¶ The names of key and/or required properties that are missing.
This is a list of strings with the names of key and/or required properties that either haven’t been set or are set to
None
.
-
repr_properties
¶ The names of the properties rendered by
__repr__()
(a list of strings).When
key_properties
is nonempty the names of the key properties are returned, otherwise a more complex selection is made (of properties defined by subclasses ofPropertyManager
whoserepr
isTrue
).
-
find_properties
(**options)[source]¶ Find an object’s properties (of a certain type).
Parameters: options – Passed on to have_property()
to enable filtering properties by the operations they support.Returns: A sorted list of strings with the names of properties.
-
have_property
(name, **options)[source]¶ Check if the object has a property (of a certain type).
Parameters: Returns: True
if the object has a property with the expected options enabled/disabled,False
otherwise.
-
render_properties
(*names)[source]¶ Render a human friendly string representation of an object with computed properties.
Parameters: names – Each positional argument gives the name of a property to include in the rendered object representation. Returns: The rendered object representation (a string). This method generates a user friendly textual representation for objects that use computed properties created using the
property_manager
module.
-
__eq__
(other)[source]¶ Enable equality comparison and hashing for
PropertyManager
subclasses.
-
__ne__
(other)[source]¶ Enable non-equality comparison for
PropertyManager
subclasses.
-
__lt__
(other)[source]¶ Enable “less than” comparison for
PropertyManager
subclasses.
-
__le__
(other)[source]¶ Enable “less than or equal” comparison for
PropertyManager
subclasses.
-
__gt__
(other)[source]¶ Enable “greater than” comparison for
PropertyManager
subclasses.
-
__ge__
(other)[source]¶ Enable “greater than or equal” comparison for
PropertyManager
subclasses.
-
__hash__
()[source]¶ Enable hashing for
PropertyManager
subclasses.This method makes it possible to add
PropertyManager
objects to sets and use them as dictionary keys. The hashes computed by this method are based on the values inkey_values
.
-
__repr__
()[source]¶ Render a human friendly string representation of an object with computed properties.
Returns: The rendered object representation (a string). This method uses
render_properties()
to render the properties whose names are given byrepr_properties
. When the object doesn’t have any key properties,__repr__()
assumes that all of the object’s properties are idempotent and may be evaluated at any given time without worrying too much about performance (refer to therepr
option for an escape hatch).
-
-
class
property_manager.
custom_property
(*args, **kw)[source]¶ Custom
property
subclass that supports additional features.The
custom_property
class implements Python’s descriptor protocol to provide a decorator that turns methods into computed properties with several additional features.The additional features are controlled by attributes defined on the
custom_property
class. These attributes (documented below) are intended to be changed by the constructor (__new__()
) and/or classes that inherit fromcustom_property
.-
cached
= False¶ If this attribute is set to
True
the property’s value is computed only once and then cached in an object’s__dict__
. The next time you access the attribute’s value the cached value is automatically returned. By combining thecached
andresettable
options you get a cached property whose cached value can be cleared. If the value should never be recomputed then don’t enable theresettable
option.See also: cached_property
andlazy_property
.
-
dynamic
= False¶ True
when thecustom_property
subclass was dynamically constructed by__new__()
,False
otherwise. Used bycompose_usage_notes()
to decide whether to link to the documentation of the subclass or not (because it’s impossible to link to anonymous classes).
-
environment_variable
= None¶ If this attribute is set to the name of an environment variable the property’s value will default to the value of the environment variable. If the environment variable isn’t set the property falls back to its computed value.
-
key
= False¶ If this attribute is
True
the property’s name is included in the value ofkey_properties
which means that the property’s value becomes part of the “key” that is used to compare, sort and hashPropertyManager
objects. There are a few things to be aware of with regards to key properties and their values:- The property’s value must be set during object initialization (the same
as for
required
properties) and it cannot be changed after it is initially assigned a value (because allowing this would “compromise” the results of the__hash__()
method). - The property’s value must be hashable (otherwise it can’t be used by the
__hash__()
method).
See also: key_property
.- The property’s value must be set during object initialization (the same
as for
-
repr
= True¶ By default
PropertyManager.__repr__()
includes the names and values of all properties that aren’tNone
inrepr()
output. If you want to omit a certain property you can setrepr
toFalse
.Examples of why you would want to do this include property values that contain secrets or are expensive to calculate and data structures with cycles which cause
repr()
to die a slow and horrible death :-).
-
required
= False¶ If this attribute is set to
True
the property requires a value to be set during the initialization of the object that owns the property. For this to work the class that owns the property needs to inherit fromPropertyManager
.See also: required_property
.The constructor of
PropertyManager
will ensure that required properties are set to values that aren’tNone
. Required properties must be set by providing keyword arguments to the constructor of the class that inherits fromPropertyManager
. WhenPropertyManager.__init__()
notices that required properties haven’t been set it raises aTypeError
similar to the type error raised by Python when required arguments are missing in a function call. Here’s an example:from property_manager import PropertyManager, required_property, mutable_property class Example(PropertyManager): @required_property def important(self): "A very important attribute." @mutable_property def optional(self): "A not so important attribute." return 13
Let’s construct an instance of the class defined above:
>>> Example() Traceback (most recent call last): File "property_manager/__init__.py", line 107, in __init__ raise TypeError("%s (%s)" % (msg, concatenate(missing_properties))) TypeError: missing 1 required argument ('important')
As expected it complains that a required property hasn’t been initialized. Here’s how it’s supposed to work:
>>> Example(important=42) Example(important=42, optional=13)
-
resettable
= False¶ If this attribute is set to
True
the property can be reset to its default or computed value usingdel
anddelattr()
. This works by removing the assigned or cached value from the object’s__dict__
.See also: mutable_property
andcached_property
.
-
usage_notes
= True¶ If this attribute is
True
inject_usage_notes()
is used to inject usage notes into the documentation of the property. You can set this attribute toFalse
to disableinject_usage_notes()
.
-
writable
= False¶ If this attribute is set to
True
the property supports assignment. The assigned value is stored in the__dict__
of the object that owns the property.See also: writable_property
,mutable_property
andrequired_property
.A relevant note about how Python looks up attributes: When an attribute is looked up and exists in an object’s
__dict__
Python ignores any property (descriptor) by the same name and immediately returns the value that was found in the object’s__dict__
.
-
static
__new__
(cls, *args, **options)[source]¶ Constructor for
custom_property
subclasses and instances.To construct a subclass:
Parameters: - args – The first positional argument is used as the name of the subclass (defaults to ‘customized_property’).
- options – Each keyword argument gives the name of an option
(
writable
,resettable
,cached
,required
,environment_variable
,repr
) and the value to use for that option (True
,False
or a string).
Returns: A dynamically constructed subclass of
custom_property
with the given options.To construct an instance:
Parameters: args – The first positional argument is the function that’s called to compute the value of the property. Returns: A custom_property
instance corresponding to the class whose constructor was called.Here’s an example of how the subclass constructor can be used to dynamically construct custom properties with specific options:
from property_manager import custom_property class WritableCachedPropertyDemo(object): @custom_property(cached=True, writable=True) def customized_test_property(self): return 42
The example above defines and uses a property whose computed value is cached and which supports assignment of new values. The example could have been made even simpler:
from property_manager import cached_property class WritableCachedPropertyDemo(object): @cached_property(writable=True) def customized_test_property(self): return 42
Basically you can take any of the custom property classes defined in the
property_manager
module and call the class with keyword arguments corresponding to the options you’d like to change.
-
__init__
(*args, **kw)[source]¶ Initialize a
custom_property
object.Parameters: Automatically calls
inject_usage_notes()
during initialization (only ifUSAGE_NOTES_ENABLED
isTrue
).
-
ensure_callable
(role)[source]¶ Ensure that a decorated value is in fact callable.
Parameters: role – The value’s role (one of ‘fget’, ‘fset’ or ‘fdel’). Raises: exceptions.ValueError
when the value isn’t callable.
-
inject_usage_notes
()[source]¶ Inject the property’s semantics into its documentation.
Calls
compose_usage_notes()
to get a description of the property’s semantics and appends this to the property’s documentation. If the property doesn’t have documentation it will not be added.
-
compose_usage_notes
()[source]¶ Get a description of the property’s semantics to include in its documentation.
Returns: A list of strings describing the semantics of the custom_property
in reStructuredText format with Sphinx directives.
-
__get__
(obj, type=None)[source]¶ Get the assigned, cached or computed value of the property.
Parameters: - obj – The instance that owns the property.
- type – The class that owns the property.
Returns: The value of the property.
-
__set__
(obj, value)[source]¶ Override the computed value of the property.
Parameters: - obj – The instance that owns the property.
- value – The new value for the property.
Raises: AttributeError
ifwritable
isFalse
.
-
__delete__
(obj)[source]¶ Reset the assigned or cached value of the property.
Parameters: obj – The instance that owns the property. Raises: AttributeError
ifresettable
isFalse
.Once the property has been deleted the next read will evaluate the decorated function to compute the value.
-
-
class
property_manager.
writable_property
(*args, **kw)[source]¶ A computed property that supports assignment.
This is a variant of
custom_property
that has thewritable
option enabled by default.
-
class
property_manager.
required_property
(*args, **kw)[source]¶ A property that requires a value to be set.
This is a variant of
writable_property
that has therequired
option enabled by default. Refer to the documentation of therequired
option for an example.
-
class
property_manager.
key_property
(*args, **kw)[source]¶ A property whose value is used for comparison and hashing.
This is a variant of
custom_property
that has thekey
andrequired
options enabled by default.
-
class
property_manager.
mutable_property
(*args, **kw)[source]¶ A computed property that can be assigned and reset.
This is a variant of
writable_property
that has theresettable
option enabled by default.
-
class
property_manager.
lazy_property
(*args, **kw)[source]¶ A computed property whose value is computed once and cached.
This is a variant of
custom_property
that has thecached
option enabled by default.
-
class
property_manager.
cached_property
(*args, **kw)[source]¶ A computed property whose value is computed once and cached, but can be reset.
This is a variant of
lazy_property
that has theresettable
option enabled by default.
property_manager.sphinx
¶
Integration with the Sphinx documentation generator.
The property_manager.sphinx
module uses the Sphinx extension API to
customize the process of generating Sphinx based Python documentation. It
modifies the documentation of PropertyManager
subclasses to include
an overview of superclasses, properties, public methods and special methods. It
also includes hints about required properties and how the values of properties
can be set by passing keyword arguments to the class initializer.
For a simple example check out the documentation of the TypeInspector
class. Yes, that means this module is being used to document itself :-).
The entry point to this module is the setup()
function.
-
property_manager.sphinx.
setup
(app)[source]¶ Make it possible to use
property_manager.sphinx
as a Sphinx extension.Parameters: app – The Sphinx application object. To enable the use of this module you add the name of the module to the
extensions
option in yourdocs/conf.py
script:extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'property_manager.sphinx', ]
When Sphinx sees the
property_manager.sphinx
name it will import this module and call thesetup()
function which will connect theappend_property_docs()
function toautodoc-process-docstring
events.
-
property_manager.sphinx.
append_property_docs
(app, what, name, obj, options, lines)[source]¶ Render an overview with properties and methods of
PropertyManager
subclasses.This function implements a callback for
autodoc-process-docstring
that generates and appends an overview of member details to the docstrings ofPropertyManager
subclasses.The parameters expected by this function are those defined for Sphinx event callback functions (i.e. I’m not going to document them here :-).
-
class
property_manager.sphinx.
TypeInspector
(**kw)[source]¶ Introspection of
PropertyManager
subclasses.Here’s an overview of the
TypeInspector
class:Superclass: PropertyManager
Public methods: format_methods()
andformat_properties()
Properties: custom_properties
,initializer_hint
,members
,methods
,overview
,properties
,public_methods
,required_hint
,special_methods
andtype
When you initialize a
TypeInspector
object you are required to provide a value for thetype
property. You can set the value of thetype
property by passing a keyword argument to the class initializer.-
custom_properties
[source]¶ A list of tuples with the names and values of custom properties.
Note
The
custom_properties
property is alazy_property
. This property’s value is computed once (the first time it is accessed) and the result is cached.
-
initializer_hint
[source]¶ A hint that properties can be set using keyword arguments to the initializer (a string or
None
).Note
The
initializer_hint
property is alazy_property
. This property’s value is computed once (the first time it is accessed) and the result is cached.
-
members
[source]¶ An iterable of tuples with the names and values of the non-inherited members of
type
.Note
The
members
property is alazy_property
. This property’s value is computed once (the first time it is accessed) and the result is cached.
-
methods
[source]¶ An iterable of method names of
type
.Note
The
methods
property is alazy_property
. This property’s value is computed once (the first time it is accessed) and the result is cached.
-
overview
[source]¶ Render an overview with related members grouped together.
Note
The
overview
property is alazy_property
. This property’s value is computed once (the first time it is accessed) and the result is cached.
-
properties
[source]¶ An iterable of tuples with property names (strings) and values (
property
objects).Note
The
properties
property is alazy_property
. This property’s value is computed once (the first time it is accessed) and the result is cached.
-
public_methods
[source]¶ An iterable of strings with the names of public methods (that don’t start with an underscore).
Note
The
public_methods
property is alazy_property
. This property’s value is computed once (the first time it is accessed) and the result is cached.
-
required_hint
[source]¶ A hint about required properties (a string or
None
).Note
The
required_hint
property is alazy_property
. This property’s value is computed once (the first time it is accessed) and the result is cached.
-
special_methods
[source]¶ An iterable of strings with the names of special methods (surrounded in double underscores).
Note
The
special_methods
property is alazy_property
. This property’s value is computed once (the first time it is accessed) and the result is cached.
-
type
[source]¶ A subclass of
PropertyManager
.Note
The
type
property is arequired_property
. You are required to provide a value for this property by calling the constructor of the class that defines the property with a keyword argument named type (unless a custom constructor is defined, in this case please refer to the documentation of that constructor). You can change the value of this property using normal attribute assignment syntax.
-
Change log¶
The change log lists notable changes to the project:
Changelog¶
The purpose of this document is to list all of the notable changes to this project. The format was inspired by Keep a Changelog. This project adheres to semantic versioning.
- Release 3.0 (2020-03-02)
- Release 2.3.1 (2018-05-19)
- Release 2.3 (2018-04-27)
- Release 2.2 (2017-06-29)
- Release 2.1 (2016-06-15)
- Release 2.0 (2016-06-15)
- Release 1.6 (2016-06-01)
- Release 1.5 (2016-06-01)
- Release 1.4 (2016-05-31)
- Release 1.3 (2015-11-25)
- Release 1.2 (2015-10-06)
- Release 1.1.1 (2015-10-04)
- Release 1.1 (2015-10-04)
- Release 1.0.1 (2015-10-04)
- Release 1.0 (2015-10-04)
Release 3.0 (2020-03-02)¶
No exciting changes, mostly just project maintenance 😇.
- Merge pull request #2: Fix deprecation warnings caused by importing
collections.Hashable
on Python 3.3+ (fixes issue #1). - Drop support for Python 2.6 and 3.4, start testing on 3.7 and 3.8.
- Change order of hints & overview in generated documentation.
- Updated to humanfriendly 8.0 (to fix deprecated imports).
- Updated the
Makefile
to use Python 3 for local development. - Switched the coveralls badge in the readme to SVG.
- Changed the Read the Docs base URL.
Release 2.3.1 (2018-05-19)¶
Minor bug fix release to sort the property names in the overview appended to class docstrings (I’m not sure what the implicit order was but it definitely wasn’t alphabetical :-p).
Release 2.3 (2018-04-27)¶
- Added
property_manager.sphinx
module to automatically generate boilerplate documentation. - Added
license
and removedtest_suite
key insetup.py
script. - Include documentation in source distributions.
- Change Sphinx documentation theme.
- Added this changelog.
Release 2.2 (2017-06-29)¶
- Decomposed
__repr__()
into property selection and rendering functionality. - Added Python 3.6 to tested and supported versions.
- Properly documented logging configuration.
- Switched Sphinx theme (default → classic).
- Refactored
setup.py
script andMakefile
:- Added wheel distributions (
setup.cfg
). - Fixed code style checks.
- Added wheel distributions (
Release 2.1 (2016-06-15)¶
Remove fancy but superfluous words from DYNAMIC_PROPERTY_NOTE
:-).
Release 2.0 (2016-06-15)¶
Easy to use PropertyManager
object hashing and comparisons.
Release 1.6 (2016-06-01)¶
Support for setters, deleters and logging.
Release 1.5 (2016-06-01)¶
- Added
set_property()
andclear_property()
functions. - Added Python 3.5 to tested and supported versions.
- Rearranged class variables and their documentation (I’m still getting up to speed with Sphinx, have been doing so for years, probably I’ll still be learning new things a few years from now :-).
Release 1.4 (2016-05-31)¶
- Only inject usage notes when applicable.
- Start using the
humanfriendly.sphinx
module.
Release 1.3 (2015-11-25)¶
Support for properties whose values are based on environment variables.
Release 1.2 (2015-10-06)¶
Made it possible to opt out of usage notes.
Release 1.1.1 (2015-10-04)¶
- Made
repr()
render only properties of subclasses. - Removed indentation from doctest formatted code samples in readme.
Release 1.1 (2015-10-04)¶
- Documented similar projects and distinguishing features.
- Improved the structure of the documentation.
Release 1.0.1 (2015-10-04)¶
- Improved usage notes of dynamically constructed subclasses.
- Added PyPI trove classifiers to
setup.py
script. - Added Travis CI configuration.
Release 1.0 (2015-10-04)¶
The initial commit and release. Relevant notes from the readme:
The property-manager package came into existence as a submodule of my executor package where I wanted to define classes with a lot of properties that had a default value which was computed on demand but also needed to support assignment to easily override the default value.
Since I created that module I’d wanted to re-use it in a couple of other projects I was working on, but adding an executor dependency just for the property_manager submodule felt kind of ugly.
This is when I decided that it was time for the property-manager package to be created. When I extracted the submodule from executor I significantly changed its implementation (making the code more robust and flexible) and improved the tests, documentation and coverage in the process.