Create a read-only representation of an arbitrary Python object.
The precondition is that the object is copy.deepcopy-able and does not have
an attribute TYPEOFSOURCE.
The use case of this function is when an API wants to give read access to
the properties of an object but in a stronger way than what a deep copy
provides. The stronger property is that it is forbidded for client code to
modify the result. As such, callable attributes are not included in the
result. If the original object is callable None is returned.
Unfortunately, much of the original type information and semantics can
be lost in the resulting representation. For example, for some x and y
such that x != y it is possible that ReadOnlyCopy(x) == ReadOnlyCopy(y).
For primitives like int, string, etc this is not an issue since ReadOnlyCopy
will return the same result as deep copy. Other times ReadOnlyCopy is
only appropriate when a collections.namedtuple of the properties of the
object are appropriate. To help restore the some of the lost information in
these namedtuple intances, the TYPEOFSOURCE attribute provides access to
the type of the source object.