The application programming interface (API) of this library package is divided into two parts: Primary and Auxiliary. The primary part consists of the core functionality for which the package is being provided: concealment and immutability of attributes and interception of API invocations. The auxiliary part consists of various functionalities, which the package internally utilizes, but which provide significant value beyond the confines of the package.

Primary API Documentation

Module lockup

Supports attribute concealment and immutability.

Also supports various related functionality, such as apprehension of fugitive exceptions at API boundaries.

class lockup.Module(name, doc=None)

Bases: module

Module whose attributes are immutable except during module definition.

Can replace the __class__ attribute on an existing module.

A copy of the module dictionary is returned when the __dict__ attribute is accessed; this is done to remove a backdoor by which attributes could be mutated.

Note

Copies of the module dictionary are mutable so as to not violate the internal expectations of Python as well as important packages, such as doctest. Ideally, these would be immutable, but cannot be as of this writing.

lockup.reclassify_module(module)

Assigns Module as class for module.

Takes either a module object or the name of a module in sys.modules. If the module has already been reclassified, then nothing is done (i.e., the operation is idempotent).

class lockup.Class(name, bases, namespace)

Bases: type

Produces classes which have immutable attributes.

Non-public attributes of each class are concealed from dir().

Note

Only class attributes are immutable. Instances of immutable classes will have mutable attributes without additional intervention beyond the scope of this package.

mro()

Return a type’s method resolution order.

class lockup.NamespaceClass(name, bases, namespace)

Bases: Class

Produces namespace classes which have immutable attributes.

Each produced namespace is a unique class, which cannot be instantiated.

Non-public attributes of each class are concealed from dir().

Warning

Although most descriptor attributes will be inert on a class, types.DynamicClassAttribute() and similar, may trigger attribute errors when accessed. However, these are a fairly rare case and are probably not needed on namespaces, in general.

mro()

Return a type’s method resolution order.

lockup.create_interception_decorator(exception_factory_provider, apprehender)

Creates function decorator to apprehend “fugitive” exceptions.

Takes an exception_factory_provider argument. This provider must be capable of providing an exception factory, which is indexed by the name invocation_validation and which has an interface that corresponds to lockup.exceptionality.our_factories.create_invocation_validation_exception().

Takes an apprehender argument, which must be a callable that accepts exactly two arguments and which returns two values. The first argument to the callable is expected to be an exception raised by the function wrapped by the decorator produced from this factory. The second argument to the callable is expected to be the function wrapped by the decorator. The first return value from the apprehender is expected to either be the expection that was passed to it or else None. The second return value from the apprehender is expected to either be an another exception or else None.

  • If both return values from the apprehender are None, then the apprehended exception will be returned directly rather than propagated as an exception.

  • If the first return value from the apprehender is the apprehended exception and the second return value is None, then propagation of the apprehended exception continues (i.e., it is re-raised).

  • If the first return value from the apprehender is the apprehended exception and the second return value is another exception, then the other exception is propagated with the apprehended exception in its custody (i.e., its __cause__).

  • If the first return value is None and the second return value is another exception, then that exception is propagated instead of the originally apprehended one with no reference to the originally apprehended one.

lockup.create_namespace(**nomargs)

Creates immutable namespaces from nominative arguments.

Module lockup.exceptions

Classes of exceptions emitted by the functionality of this package.

Omniexception is the ancestor of all the exception classes. It has an exception_labels attribute which allows instances of it to bear information about exceptions beyond what a class alone can convey. As a principle, we try to avoid class hierarchies and instead use labels. However, sometimes the Python implementation or the test machinery expect exception classes which are explicitly subclassed from certain Python builtin exception classes. So, variants of the omniexception class, which are fused to necessary Python builtin exception classes, are also provided. Exceptions from the fused classes can be matched by their corresponding builtin exception classes or by their ancestral exception classes from this module:

>>> import csv
>>> type( csv )
<class 'module'>
>>> import lockup
>>> from lockup.exceptions import InvalidOperation
>>> lockup.reclassify_module( csv )
>>> type( csv )
<class 'lockup.module.Module'>
>>> try: del csv.reader
... except AttributeError as exc: type( exc ).mro( )
...
[<class 'lockup.exceptions.ImpermissibleAttributeOperation'>, <class 'lockup.exceptions.ImpermissibleOperation'>, <class 'lockup.exceptions.InvalidOperation'>, <class 'lockup.exceptions.Omniexception'>, <class 'TypeError'>, <class 'AttributeError'>, <class 'Exception'>, <class 'BaseException'>, <class 'object'>]
>>> try: del csv.reader
... except InvalidOperation as exc: pass
...
>>> try: del csv.nonexistent_attribute
... except InvalidOperation as exc: type( exc ).mro( )
...
[<class 'lockup.exceptions.InaccessibleAttribute'>, <class 'lockup.exceptions.InvalidOperation'>, <class 'lockup.exceptions.Omniexception'>, <class 'AttributeError'>, <class 'Exception'>, <class 'BaseException'>, <class 'object'>]
exception lockup.exceptions.AbsentImplementation(*posargs, exception_labels=None, **nomargs)

Bases: InvalidOperation, NotImplementedError

Complaint about attempt to execute nonexistent implementation.

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception lockup.exceptions.ImpermissibleAttributeOperation(*posargs, exception_labels=None, **nomargs)

Bases: ImpermissibleOperation, AttributeError

Complaint about impermissible attribute operation.

Cannot use ImpermissibleOperation because some packages, such as Sphinx Autodoc, expect an AttributeError.

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception lockup.exceptions.ImpermissibleOperation(*posargs, exception_labels=None, **nomargs)

Bases: InvalidOperation, TypeError

Complaint about impermissible operation.

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception lockup.exceptions.InaccessibleAttribute(*posargs, exception_labels=None, **nomargs)

Bases: InvalidOperation, AttributeError

Complaint about attempt to retrieve inaccessible attribute.

Cannot use InvalidOperation because some Python internals expect an AttributeError.

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception lockup.exceptions.IncorrectData(*posargs, exception_labels=None, **nomargs)

Bases: InvalidOperation, TypeError, ValueError

Complaint about incorrect data for invocation or operation.

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception lockup.exceptions.InvalidOperation(*posargs, exception_labels=None, **nomargs)

Bases: Omniexception, Exception

Complaint about invalid operation.

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception lockup.exceptions.InvalidState(*posargs, exception_labels=None, **nomargs)

Bases: Omniexception, RuntimeError

Alert about invalid internal state in the package.

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception lockup.exceptions.Omniexception(*posargs, exception_labels=None, **nomargs)

Bases: BaseException

Base for all exceptions in the package.

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

Auxiliary API Documentation

Module lockup.exceptionality

Assortment of exception management utilities.

lockup.exceptionality.intercept_exception_class_provider(provider, invocation)

Encloses exception class provider with interceptor.

lockup.exceptionality.intercept_exception_factory_provider(provider, invocation)

Encloses exception factory provider with interceptor.

lockup.exceptionality.our_exception_class_provider(name)

Provides package-internal exception class.

The exception classes are drawn from the lockup.exceptions module.

lockup.exceptionality.our_exception_factory_provider(name)

Provides package-internal exception factory.

The exception factories are drawn from this module and are functions which have names that start with create_ and end with _exception.

Module lockup.exceptionality.our_factories

Factories to produce exceptions with standard message formats.

Each factory takes, as its first argument, an exception class provider. This provider is expected to take a single argument, which is the name of an exception class among those defined in lockup.exceptions and provide an equivalent class. The exception class provider used internally within this package provides exactly those classes. However, you may define your own which provides other classes, translating the names as necessary.

class lockup.exceptionality.our_factories.ExtraData(positional_arguments=(), nominative_arguments=mappingproxy({}), exception_labels=mappingproxy({}))

Bases: object

Data transfer object for extra exception data.

Carries extra positional arguments, beyond the first one, which is assumed to be the message. Also carries extra nominative arguments to be applied during exception construction.

Allows for specification of extra exception labels beyond what an exception factory would naturally provide.

lockup.exceptionality.our_factories.create_argument_validation_exception(exception_class_provider, name, invocation, expectation, extra_data=<lockup.exceptionality.our_factories.ExtraData object>)

Creates error with context about invalid argument.

Given an argument name, callable object, and an expectation about the argument (as text), produces an exception of a class equivalent to lockup.exceptions.IncorrectData.

lockup.exceptionality.our_factories.create_attribute_immutability_exception(exception_class_provider, name, object_, action='assign', extra_data=<lockup.exceptionality.our_factories.ExtraData object>)

Creates error with context about immutable attribute.

Given an attribute name, object which contains the attribute, and the name of an action upon the attribute, produces an exception of a class equivalent to lockup.exceptions.ImpermissibleAttributeOperation.

lockup.exceptionality.our_factories.create_attribute_indelibility_exception(exception_class_provider, name, object_, extra_data=<lockup.exceptionality.our_factories.ExtraData object>)

Creates error with context about indelible attribute.

Given an attribute name and object which contains the attribute, produces an exception of a class equivalent to lockup.exceptions.ImpermissibleAttributeOperation.

lockup.exceptionality.our_factories.create_attribute_name_illegality_exception(exception_class_provider, name, extra_data=<lockup.exceptionality.our_factories.ExtraData object>)

Creates error about illegal attribute name.

Given an attribute name, produces an exception of a class equivalent to lockup.exceptions.IncorrectData.

lockup.exceptionality.our_factories.create_attribute_nonexistence_exception(exception_class_provider, name, object_, extra_context=None, extra_data=<lockup.exceptionality.our_factories.ExtraData object>)

Creates error with context about nonexistent attribute.

Given an attribute name, object which allegedly does not contain the attribute, and, optionally, some extra context (as text), produces an exception of a class equivalent to lockup.exceptions.InaccessibleAttribute.

lockup.exceptionality.our_factories.create_attribute_noninvocability_exception(exception_class_provider, name, object_, extra_context=None, extra_data=<lockup.exceptionality.our_factories.ExtraData object>)

Creates error with context about noninvocable attribute.

Given an attribute name, object which contains the attribute, and, optionally, some extra context (as text), produces an exception of a class equivalent to lockup.exceptions.InvalidOperation.

lockup.exceptionality.our_factories.create_class_attribute_rejection_exception(exception_class_provider, name, class_, extra_data=<lockup.exceptionality.our_factories.ExtraData object>)

Creates error with context about class attribute rejection.

Given an attribute name and the class on which it is supposed to be defined, produces an exception of a class equivalent to lockup.exceptions.ImpermissibleOperation.

lockup.exceptionality.our_factories.create_fugitive_apprehension_exception(exception_class_provider, fugitive, invocation, extra_data=<lockup.exceptionality.our_factories.ExtraData object>)

Creates error with context about fugitive exception apprehension.

Given an apprehended fugitive exception and the callable on whose boundary it was apprehended, produces an exception of a class equivalent to lockup.exceptions.InvalidState.

lockup.exceptionality.our_factories.create_impermissible_instantiation_exception(exception_class_provider, class_, extra_data=<lockup.exceptionality.our_factories.ExtraData object>)

Creates error with context about impermissible instantiation.

Given a class, produces an exception of a class equivalent to lockup.exceptions.ImpermissibleOperation.

lockup.exceptionality.our_factories.create_implementation_absence_exception(exception_class_provider, invocation, variant_name, extra_data=<lockup.exceptionality.our_factories.ExtraData object>)

Creates error about absent implementation of invocable.

Given a callable object and the name of some platform, produces an exception of a class equivalent to lockup.exceptions.AbsentImplementation.

lockup.exceptionality.our_factories.create_inaccessible_entity_exception(exception_class_provider, name, expectation, extra_data=<lockup.exceptionality.our_factories.ExtraData object>)

Creates error with context about inaccessible entity.

Given the name of some entity and an expectation about access (as text), produces an exception of a class equivalent to lockup.exceptions.InvalidOperation.

lockup.exceptionality.our_factories.create_invalid_state_exception(exception_class_provider, message, package_name, extra_data=<lockup.exceptionality.our_factories.ExtraData object>)

Creates error with context about invalid state.

Given a message and a complete package name, produces an exception of a class equivalent to lockup.exceptions.InvalidState.

lockup.exceptionality.our_factories.create_invocation_validation_exception(exception_class_provider, invocation, cause, extra_data=<lockup.exceptionality.our_factories.ExtraData object>)

Creates error with context about invalid invocation.

Given a callable and a description of the discrepancy between its expected parameters and the arguments used to invoke it, produces an exception of a class equivalent to lockup.exceptions.IncorrectData.

lockup.exceptionality.our_factories.create_return_validation_exception(exception_class_provider, invocation, expectation, position=None, extra_data=<lockup.exceptionality.our_factories.ExtraData object>)

Creates error with context about invalid return value.

Given a callable, an expectation about a return value from it, and, optionally, the position of the return value, produces an exception of a class equivalent to lockup.exceptions.InvalidState.

lockup.exceptionality.our_factories.provide_exception_class(name)

Provides package-internal exception class.

The exception classes are drawn from the lockup.exceptions module.

lockup.exceptionality.our_factories.provide_exception_factory(name)

Provides package-internal exception factory.

The exception factories are drawn from this module and are functions which have names that start with create_ and end with _exception.

Module lockup.nomenclature

Nomenclatural utilities.

lockup.nomenclature.calculate_apex_package_name(source)

Calculates name of apex package from module object or package name.

lockup.nomenclature.calculate_argument_label(name, signature)

Produces human-comprehensible label for argument.

lockup.nomenclature.calculate_attribute_label(attribute, label_base)

Produces human-comprehensible label for attribute.

lockup.nomenclature.calculate_class_label(classes, attribute_label=None)

Produces human-comprehensible label for class or tuple of classes.

Each provided class may be a class object or namespace dictionary that is present during class creation.

lockup.nomenclature.calculate_instance_label(object_, attribute_label=None)

Produces human-comprehensible label for instance of class.

lockup.nomenclature.calculate_invocable_label(invocable)

Produces human-comprehensible label for invocable object.

An invocable object may be a function, bound method, class, or invocable instance of a class.

lockup.nomenclature.calculate_label(object_, attribute_label=None)

Produces human-comprehensible label, based on classification.

lockup.nomenclature.calculate_module_label(module, attribute_label=None)

Produces human-comprehensible label for module.

lockup.nomenclature.calculate_routine_label(routine)

Produces human-comprehensible label for routine.

lockup.nomenclature.is_python_identifier(name)

Is object a legal Python identifier? Excludes Python keywords.

lockup.nomenclature.module_qualify_class_name(class_)

Concatenates module name and qualified name of class.

Also supports class namespace dictionaries.

Module lockup.reflection

Class reflection facilities.

The type of type is type:

>>> type( type ).__name__
'type'

You can imbue a class with similar behavior, if necessary:

>>> class Class( type ): pass
...
>>> type( Class ).__name__
'type'
>>> import lockup.reflection
>>> lockup.reflection.reassign_class_factory( Class, Class, assert_implementation = False )  
...
>>> type( Class ).__name__  
'Class'

The above technique is used internally within this package itself.

Note

This function only works on some flavors of Python, such as the reference implementation (CPython) and Pyston, at present. You can still use this package on other flavors of Python, but the reflection operation may not be implemented.

lockup.reflection.reassign_class_factory(class_, factory, assert_implementation=True)

Assigns new class factory (metaclass) to class.

This technique is a way to overcome the problem of infinite regress when a class needs behaviors that it could otherwise only get from another class. Within this package, it is used to allow a class factory to enforce immutability upon itself, for example.

If assert_implementation is true, then an exception will be raised if no reflector is implemented for the executing flavor of Python.

Module lockup.validators

Validation functions.

lockup.validators.validate_argument_class(exception_factory_provider, argument, classes, name, invocation)

Validates argument as an instance of one or more classes.

lockup.validators.validate_argument_invocability(exception_factory_provider, argument, name, invocation)

Validates argument as an invocable object, such as a function.

lockup.validators.validate_attribute_existence(exception_factory_provider, name, object_, extra_context=None)

Validates attribute existence on object.

lockup.validators.validate_attribute_invocability(exception_factory_provider, name, object_, extra_context=None)

Validates attribute invocability on object.

Implies attribute existence validation.

lockup.validators.validate_attribute_name(exception_factory_provider, name)

Validates attribute name as Python identifier.

Module lockup.visibility

Functions for controlling and determining attribute visibility.

lockup.visibility.is_operational_name(name)

Returns True if name is operational.

An operational name begins and ends with a double underscore (__).

lockup.visibility.is_public_name(name)

Returns True if name is user-public.

A user-public name does not begin with an underscore (_).

lockup.visibility.is_public_or_operational_name(name)

Returns True if name is user-public or operational.

See is_public_name() and is_operational_name() for details.

lockup.visibility.select_public_attributes(class_, object_, *, includes=(), excludes=())

Selects all attributes with user-public names on object.

Can optionally include specific attributes that would not be selected under normal operation and can exclude specific attributes that would selected under normal operation.