Package: pytilities
Pytilities is a python3 utility library.LinksPytilities homepageDocumentationFeaturesAspect oriented programming:Create Aspects to bundle adviceApply advice to any attribute of an instance or all instances of a class.
Can even be applied to attributes that don’t exist on the instance (i.e.
create it). Can also be applied to any attribute of an object.Event dispatching: Observer/Subject like event dispatching with wrappers
for hiding events on dispatchers and combining dispatchersFunction overloadingBasic geometry: Vector, Rectangle classesVarious: cross platform infinity number, …Changelog1.2.0pytilities.aopAdvising is more KISS now. You map your advice in a plain dictionary, instead
of using _advise. ‘*’ advice is now gone, instead you can use a special
dictionary like object: pytilities.dictionary.FunctionMap. It allows for ‘*’
advice and more.Changed:Aspect:Added:_advice_mappings: Mapping of (access, attribute_name) to advice. Note
that ‘*’ is not a valid attribute_name, useFunctionMapinstead of
the old ‘*’ advice. If you useFunctionMapyou should set_undefined_keysto True._undefined_keys: set to True if _advice_mappings provides infinite
mappingsRemoved:_advise: use_advice_mappingsinsteadFixed:fixed a special case of invalid call advising, see
pytilities.test.aop.calladvisespecialcasepytilities.aop.aspectsFixed:View: the aspect did not correctly enable its aspect upon calling
callables through the viewpytilities.delegationDelegation is more KISS now. The complex Profile class was removed in favor
of plain dictionaries (and those of pytilities.dictionary).in_profileis
replaced by the more flexible and KISSmapped.Added:mapped: adds an attribute to a mapping in a format that can be used
as argument to DelegationAspect. You could also use it as a base for the
_advice_mappings of your Aspect, …mapped_class: required on a class formappedto workChanged:DelegationAspect:no longer expects a Profile parameter, instead it expects a mapping of
(access, source_attribute_name) to target_attribute_name; where
access is ‘get’, ‘set’,  or ‘delete’, as opposed to ‘r’, ‘w’, or
‘d’.Removed:profile_carrier: usemapped_classinsteadin_profile: usemappedinsteadProfile: replaced by plain dictionaries (This is more flexible and KISS
than the vague Profile interface)pytilities.dictionary (new)Added:FunctionMap: A Mapping that uses a function to generate its valuespytilities.eventChanged:DispatcherSwitch: now has its ‘delegation profile’ stored in
public_mappingDispatcher: now has its ‘delegation profile’ stored in
public_mapping and default_mappingpytilities.testsChanged:is_private: now only returns True for names matching __name or
_SomeClass_name.Fixed:is_special: returned False on special attributes1.1.0pytilities.aopMade aop more KISS so it’s easier to understand, use (and maintain):Distinction between class and instance advice may now be forgotten, there’s
only advice. Classes act as wildcards now, e.g. aspect.apply(Class) means
apply to all instances of Class and Class itself.You can now apply an aspect to all instances from a class and then exclude an
instance from that advice by unapplying it afterwards.Improved test coverage (less bugs now).Added:advisor.get_applied_aspects(obj)AOPExceptionyield suppress_aspect: context manager that prevents the current aspect
from having its advice executed till the end of the contextyield advised_attribute: replaces (yield name, yield advised).yield advised_instance: returns the instance to which the aspect was applied
(or the class in case the advised is a static/class method)Changed:Aspect:_advise: You can no longer advise a member more than once. This
includes trying to advise ‘*’ and some regular member at the same time.
(this makes Aspect more KISS, you can workaround this limitation
using multiple aspects)is_enabled: now returns False for objects to which it is not appliedapply: now applies the aspect to all instances of cls and cls
itself when supplied a classunapply: now unapplies the aspect on all instances of cls and cls
itself when supplied a classunapply_all: now unapplies all aspects on all instances of cls
and cls itself when supplied a classis_applied: returns True, if given object is in
advisor.get_applied_aspects(obj)Removed:yield name: Removed in favor of the cleareryield advised_attributeyield advised: Removed in favor of the cleareryield advised_attributeyield obj: Removed in favor of the cleareryield advised_instanceSupport for advising modules: It has become too hard too maintain this
feature while there are decent workarounds for this lack:Put your functions in a class with staticmethods or classmethodsOr use the singleton pattern.And then apply the aspect to that class.Fixes:advisor.unapply_all: forgot to implement ityield advisedreturned the wrong callable on call accessWhen trying to get an unexisting attribute after having had advice
applied and unapplied to it, the object would no longer throw
AttributeError on get accessAspect.enableandAspect.disablehad no effectpytilities.aop.aspectsAdded:ImmutableAttributeExceptionChanged:ImmutableAspect: as required by the fix (see below):
- it can now only be applied on objects with AOPMeta as metaclass
- it now raises ImmutableAttributeException on attempts to mutateFixes:create_view: did not enable its aspect on accessImmutableAspect: it only worked for detecting change on setters, it now
detects every change.pytilities.descriptorsAdded and refactored testsAdded:DereferencedBoundDescriptor: like BoundDescriptor but takes 2 descriptors
as args that are dereferenced(/read/getted) on each call.Changed:BoundDescriptor:special_dereferenceparameter was removedinstance arg will no longer be dereferenced when a descriptor arg is
passedIf you need any of the two above, use DereferencedBoundDescriptor.
(splitting the class in two like this would make it more intuitive to use)1.0.1Included project.py in release so that unit tests can be run1.0.0The library moved to python3, older python versions are no longer supported.
There a lot of changes, breaking quite a bit of the previous interface. All
changes are listed below.pytilitiesAdded:get_annotations: gets annotations of an object, allows to add new ones,
…get_attr_name, get_attr_value, has_attr_name, has_attr_value: gets an
attribute, bypassing regular lookup (no descriptor.__get__, …, does
support inheritance though)Removed:AttributeCollection, AttributeCollectionBase: use aop instead (see User
Guide)Changed:mangle:You can now pass an instance as well.Small fix involving class names that start with a ‘_’pytilities.aopThis package brings aspect oriented language features to python (in a handy
format). You can apply advice on classes and instances, using aspects that can
be applied and unapplied, enabled, disabled, …Added:advisor: singleton that aspects use to give advice (you shouldn’t use
this directly, derive from Aspect and use its methods instead)proceed, return_close, return_, arguments, advised, obj, name yields for
advice functionsAspect: base class to write your own aspects with (you are not required
to use this, but it is greatly recommended)AOPMeta: classes that are given * advice require to have AOPMeta as
metaclass, other advised classes may benefit from this metaclass as it
reduces memory usagepytilities.delegationAdded:DelegationAspect: delegate attributes from a source instance/cls to a
target. Only supports direct mappings (mappings with the same source and
target attributes).in_profile, profile_carrier: used to more easily place some profiles on a
classChanged:ProfileRemoved:Delegator, DelegatorFactory: use delegate or any of the other
possibilities listed in the User Guide insteaddelegator_factory: use profile_carrier instead.delegated: use in_profile instead.delegate: use DelegationAspect instead. You may want to read about AOP in
the user guide firstpytilities.descriptors (new)Added:AttributeDescriptor: turns a regular attribute into a descriptorDereferencedDescriptor: returns inner_desc.get.get, sets
inner_desc.get.set, …BoundDescriptor: binds an instance to a descriptor, much like bound
methodsRestrictedDescriptor: strip of the get, set or del of a descriptorpytilities.eventRemoved:dispatcher, dispatcherswitch (decorators): normally you’d send events
from an aspect as it’s a crosscutting concern, so these no longer have to
be supported. Use a custom Aspect + DelegationAspect instead.pytilities.geometryAdded:DiscreteVector, DiscreteRectangle: A Vector/Rectangle with a discrete
coordinate space. All aspects and views for Vector/Rectangle work on
these as well.verbose_rectangle_aspect, verbose_vector_aspect: Aspects to make a
Rectangle/Vector send out (change) events.ImmutableRectangle, ImmutableVector: immutable views of a
Rectangle/Vectorimmutable_rectangle_aspect, immutable_vector_aspect: makes a
Rectangle/Vector immutableChanged:Vector, Rectangle: Due to a change in int division mechanisms in python3,
these classes will always operate with a continuous coordinate space. I.e
if your vector has coords (3, 1), then when divided by 2 they become
(1.5, 0.5) and not (1, 0) as they used to be in previous versions. Use
DiscreteVector and DiscreteRectangle instead, to get similar behaviour
back.Vector, DiscreteVector: have an extra overload for assign that accepts
(x,y) as argsRemoved:BoundVector: use Vector directly instead (use its bound properties
overload)VerboseVector: make a Vector and do verbose_vector_aspect.apply(v)
instead. This works for DiscreteVectors as well.VerboseRectangle: make a Rectangle and do
verbose_rectangle_aspect.apply(v) instead. This works for DiscreteVectors
as well.pytilities.overloadingChanged:overloaded: its returned function now has a process_args method as wellParameter: its ctor was incorrectly overloaded (ironically). This has
been fixed, its overloads changed slightly because of this.pytilities.infinity (new)Provides a cross-platform alternative to float(‘inf’).Added:infinity, negative_infinity, nanis_infinitypytilities.testsAdded:is_public, is_protected, is_private, is_special: attribute name checks0.1.4Mangle, mangling and event.dispatcher: fixed a slight name clashOverhauled testing, it is now easier to useRemoved inheritance feature of DelegatorFactory, it was too vagueRemoved __init_delegation_profiles, there are other ways to achieve the same
thingChanged the DelegatorFactory interface so that it is hopefully more intuitive
to useAdded all set operators to delegation.ProfileAdded more tests and fixed some docstringsRestrictedDispatcher: Made allow and disallow mutually exclusive. It made no
sense to specify both0.1.3Added html reference documentation0.1.2Added runtests.py, which allows running unit testsAdded the types package (forgot this in last release)0.1.1Fixed: the last release wouldn’t parse0.1.0Initial release: delegation tools, events, overloading, …