Package: accessify
accessifyGetting startedWhat is accessifyAccess modifiersMotivationInterfacesMotivationHow to installUsageAccess modifiersPrivateProtectedOther featuresInterfacesSingle interfaceMultiple interfacesException throws declarationDisable checkingContributingReferencesGetting startedWhat is accessifyaccessifyis aPythondesign kit that provides:interfaces,declared exceptions throws,class members accessibility levels.that could be combined with each other to make your code slim and this library usage more justified.Access modifiersAccess level modifiers determine whether other classes can use a particular field or invoke a particular method.
Accessibility levels are presented from the box in the languages likeC++,C#andJava.classCar{privatestringStartEngine(){// Code here.}}ButPythondoes not have this in the same way.MotivationWe're all consenting adults herethat is the  part of thePython philosophythat relies on human factor instead of the interpreter.There is aPython conventionthat is to use an underscore prefix for protected and private members, that is a bit ugly.
Isn't it? For instance, for the following piece of code that provides class a private member.classCar:def__start_engine(self,*args,**kwargs):passMoreover, private and protected methods could be easily accessed outside the class. This is really a point to postpone the
correct design of the system to the backlog, increasing the technical debt.classCar:def_start_engine(self,*args,**kwargs):passdef__start_engine(self,*args,**kwargs):passcar=Car()car._start_engine()car._Car__start_engine()InterfacesAn interface is a contract specifying a set of methods and properties which required to be available on any implementing class.
If the class implements an interface, but does not realize its method, corresponding errors should be raised. Interfaces are presented from the box in
the languages likeC++,C#andJava.interfaceHumanInterface{publicstringEatFood();}classHuman:HumanInterface{publicstringEatFood(){// Code here.}}ButPythondoes not have this in the same way.MotivationThe interface makes checks during the implementation creation, but not actually while execution likeabcmodule inPython.The interface requires that implementation's method arguments match with arguments declared in interfaces,abc— not.A lot of libraries that provide interfaces are no longer supported.A lot of libraries that provide interfaces require you to write a lot of code to use its functionality, this library — not.How to installUsingpipinstall the package from thePyPi.$pip3installaccessifyUsageAccess modifiersPrivatePrivate members are accessible only within the body of the class.In this example, theCarclass contains a private member namedstart_engine. As a private member, they cannot be accessed
except by member methods. The private memberstart_engineis accessed only by way of a public method calledrun.fromaccessifyimportprivateclassCar:@privatedefstart_engine(self):return'Engine sound.'defrun(self):returnself.start_engine()if__name__=='__main__':car=Car()assert'Engine sound.'==car.run()car.start_engine()The code above will produce the following traceback.Traceback(mostrecentcalllast):File"examples/access/private.py",line24,in<module>car.start_engine()File"/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/accessify/main.py",line92,inprivate_wrapperclass_name=instance_class.__name__,method_name=method.__name__,
accessify.errors.InaccessibleDueToItsProtectionLevelException:Car.start_engine()isinaccessibleduetoitsprotectionlevelTest it out using theexamples.
Get the example that contains the code above bycurland run it bypython3.$curl-Lhttps://git.io/fhASP>private.py
$python3private.pyChild classes cannot access parent private members.In this example, theCarclass contains a private member namedstart_engine. As a private member, they cannot be accessed
from the child classes,Teslain our case. So overridden methodrunbyTeslaclass cannot use the parent'sstart_enginemember.fromaccessifyimportprivateclassCar:@privatedefstart_engine(self):return'Engine sound.'classTesla(Car):defrun(self):returnself.start_engine()if__name__=='__main__':tesla=Tesla()tesla.run()The code above will produce the following traceback.Traceback(mostrecentcalllast):File"examples/inheritance/private.py",line23,in<module>tesla.run()File"examples/inheritance/private.py",line18,inrunreturnself.start_engine()File"/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/accessify/main.py",line94,inprivate_wrapperclass_name=class_contain.__name__,method_name=method.__name__,
accessify.errors.InaccessibleDueToItsProtectionLevelException:Car.start_engine()isinaccessibleduetoitsprotectionlevelTest it out using theexamples.
Get the example that contains the code above bycurland run it bypython3.$curl-Lhttps://git.io/fhASX>inheritence_private.py
$python3inheritence_private.pyProtectedA protected member is accessible within its class and by derived class instances.In this example, theCarclass contains a protected member namedstart_engine. As a protected member, they cannot be accessed
except by member methods. The protected memberstart_engineis accessed only by way of a public method calledrun.fromaccessifyimportprotectedclassCar:@protecteddefstart_engine(self):return'Engine sound.'defrun(self):returnself.start_engine()if__name__=='__main__':car=Car()assert'Engine sound.'==car.run()car.start_engine()The code above will produce the following traceback.Traceback(mostrecentcalllast):File"examples/access/protected.py",line21,in<module>car.start_engine()File"/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/accessify/main.py",line134,inprotected_wrapperclass_name=instance_class.__name__,method_name=method.__name__,
accessify.errors.InaccessibleDueToItsProtectionLevelException:Car.start_engine()isinaccessibleduetoitsprotectionlevelTest it out using theexamples.
Get the example that contains the code above bycurland run it bypython3.$curl-Lhttps://git.io/fhASM>protected.py
$python3protected.pyChild classes have access to those protected members.In this example, theCarclass contains a protected member namedstart_engine. As a protected member, they can be accessed
from the child classes,Teslain our case. So overridden methodrunbyTeslaclass can use the parent'sstart_enginemember.fromaccessifyimportprotectedclassCar:@protecteddefstart_engine(self):return'Engine sound.'classTesla(Car):defrun(self):returnself.start_engine()if__name__=='__main__':tesla=Tesla()assert'Engine sound.'==tesla.run()The code will work without errors.Test it out using theexamples.
Get the example that contains the code above bycurland run it bypython3.$curl-Lhttps://git.io/fhASD>inheritence_protected.py
$python3inheritence_protected.pyOther featuresTheaccessifydecorator removes private and protected members from classdir.fromaccessifyimportaccessify,private@accessifyclassCar:@privatedefstart_engine(self):return'Engine sound.'if__name__=='__main__':car=Car()assert'start_engine'notindir(car)Test it out using theexamples.
Get the example that contains the code above bycurland run it bypython3.$curl-Lhttps://git.io/fhASy>dir.py
$python3dir.pyInterfacesSingle interfaceWhen you declare that class implements an interface, a class should implementall methodspresented in the interface.In this example, there is an interface calledHumanInterfacethat contains two methodsloveandeat. Also, there is
a classHumanthat implements the interface butmissed method «eat», so the corresponding error should be raised.fromaccessifyimportimplementsclassHumanInterface:@staticmethoddefeat(food,*args,allergy=None,**kwargs):passif__name__=='__main__':@implements(HumanInterface)classHuman:passThe code above will produce the following traceback.Traceback(mostrecentcalllast):File"examples/interfaces/single.py",line18,in<module>@implements(HumanInterface)File"/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/accessify/interfaces.py",line66,indecoratorinterface_method_arguments=interface_method.arguments_as_string,
accessify.errors.InterfaceMemberHasNotBeenImplementedException:classHumandoesnotimplementinterfacememberHumanInterface.eat(food,args,allergy,kwargs)Test it out using theexamples.
Get the example that contains the code above bycurland run it bypython3.$curl-Lhttps://git.io/fhh2V>single_method.py
$python3single_method.pyWhen you declare that class implements an interface, a class should implement all methods that presented in the interface
includingnumber, order and naming of the accepting arguments.In this example, there is an interface calledHumanInterfacethat contains two methodsloveandeat. Also, there is
a classHumanthat implements the interface butmissed 3 of 4 arguments for method «eat», so the corresponding error should be raised.fromaccessifyimportimplementsclassHumanInterface:@staticmethoddefeat(food,*args,allergy=None,**kwargs):passif__name__=='__main__':@implements(HumanInterface)classHuman:@staticmethoddefeat(food):passThe code above will produce the following traceback.Traceback(mostrecentcalllast):File"examples/interfaces/single_arguments.py",line16,in<module>@implements(HumanInterface)File"/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/accessify/interfaces.py",line87,indecoratorinterface_method_arguments=interface_method.arguments_as_string,
accessify.errors.InterfaceMemberHasNotBeenImplementedWithMismatchedArgumentsException:classHumanimplementsinterfacememberHumanInterface.eat(food,args,allergy,kwargs)withmismatchedargumentsTest it out using theexamples.
Get the example that contains the code above bycurland run it bypython3.$curl-Lhttps://git.io/fhh2w>single_arguments.py
$python3single_arguments.pyWhen you declare that class implements an interface, a class should implement all methods that presented in the interface
including number, order and naming of the accepting arguments andaccess modifier type.In this example, there is an interface calledHumanInterfacethat contains two methodsloveandeat. Also, there is
a classHumanthat implements the interface butmissed private access modifier type for method «eat», so the corresponding
error should be raised.fromaccessifyimportimplements,privateclassHumanInterface:@private@staticmethoddefeat(food,*args,allergy=None,**kwargs):passif__name__=='__main__':@implements(HumanInterface)classHuman:@staticmethoddefeat(food,*args,allergy=None,**kwargs):passThe code above will produce the following traceback.Traceback(mostrecentcalllast):File"examples/interfaces/single_access.py",line18,in<module>@implements(HumanInterface)File"/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/accessify/interfaces.py",line77,indecoratorinterface_method_name=interface_method.name,
accessify.errors.ImplementedInterfaceMemberHasIncorrectAccessModifierException:Human.eat(food,args,allergy,kwargs)mismatchesHumanInterface.eat()memberaccessmodifier.Test it out using theexamples.
Get the example that contains the code above bycurland run it bypython3.$curl-Lhttps://git.io/fhh2r>single_access.py
$python3single_access.pyMultiple interfacesA class could implement multiple interfaces.When you declare that class that implements a bunch of interfaces, a class should implement all method that presented in
each interface including number, order and naming of the accepting arguments and access modifier type.In this example, there are an interfaceHumanSoulInterfacethat contains a method calledloveand interfaceHumanBasicsInterfacethat
contains a method calledeat. Also, there is a classHumanthat implements methodlovefrom the first interface, butmissed method «eat»from the second one, so the corresponding error should be raised.fromaccessifyimportimplementsclassHumanSoulInterface:deflove(self,who,*args,**kwargs):passclassHumanBasicsInterface:@staticmethoddefeat(food,*args,allergy=None,**kwargs):passif__name__=='__main__':@implements(HumanSoulInterface,HumanBasicsInterface)classHuman:deflove(self,who,*args,**kwargs):passThe code above will produce the following traceback.Traceback(mostrecentcalllast):File"examples/interfaces/multiple.py",line19,in<module>@implements(HumanSoulInterface,HumanBasicsInterface)File"/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/accessify/interfaces.py",line66,indecoratorinterface_method_arguments=interface_method.arguments_as_string,
accessify.errors.InterfaceMemberHasNotBeenImplementedException:classHumandoesnotimplementinterfacememberHumanBasicsInterface.eat(food,args,allergy,kwargs)Test it out using theexamples.
Get the example that contains the code above bycurland run it bypython3.$curl-Lhttps://git.io/fhh2o>multiple.py
$python3multiple.pyException throws declarationWhen you declare that interface method throws a particular exception, a class method that implement interface should
contain code in the body that raise this exception.You can declare that the interface method throws multiple exceptions.In this example, exceptionHumanDoesNotExistsErrorand exceptionHumanAlreadyInLoveErrorare declared to be raised by
theHumanclass method calledlove, but methodmissed to raise the second exception, so the corresponding error should be raised.fromaccessifyimportimplements,throwsclassHumanDoesNotExistsError(Exception):passclassHumanAlreadyInLoveError(Exception):passclassHumanInterface:@throws(HumanDoesNotExistsError,HumanAlreadyInLoveError)deflove(self,who,*args,**kwargs):passif__name__=='__main__':@implements(HumanInterface)classHuman:deflove(self,who,*args,**kwargs):ifwhoisNone:raiseHumanDoesNotExistsError('Human whom need to love does not exist.')The code above will produce the following traceback.Traceback(mostrecentcalllast):File"examples/interfaces/throws.py",line21,in<module>@implements(HumanInterface)File"/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/accessify/interfaces.py",line103,indecoratorclass_method_arguments=class_member.arguments_as_string,
accessify.errors.DeclaredInterfaceExceptionHasNotBeenImplementedException:DeclaredexceptionHumanAlreadyInLoveErrorbyHumanInterface.love()memberhasnotbeenimplementedbyHuman.love(self,who,args,kwargs)Test it out using theexamples.
Get the example that contains the code above bycurland run it bypython3.$curl-Lhttps://git.io/fhh26>throws.py
$python3throws.pyDisable checkingYou can disable allaccessifychecks. For instance, in the production, when you shouldn't check it because it already was checked
in the development. Use the following environment variable then:exportDISABLE_ACCESSIFY=TrueContributingClone the project and install requirements:$gitclonegit@github.com:dmytrostriletskyi/accessify.git&&cdaccessify
$pip3install-rrequirements-dev.txt
$pip3install-rrequirements-tests.txtIf you prefer working with theDockerand wanna easily changePythonenvironments, follow:$gitclonegit@github.com:dmytrostriletskyi/accessify.git&&cdaccessify
$exportACCESSIFY_PYTHON_VERSION=3.4
$dockerbuild--build-argACCESSIFY_PYTHON_VERSION=$ACCESSIFY_PYTHON_VERSION-taccessify.-fDockerfile-python3.x
$dockerrun-v$PWD:/accessify--nameaccessifyaccessifyEnter the container bash, checkPythonversion and run tests:$dockerexec-itaccessifybash
$root@36a8978cf100:/accessify#python--version
$root@36a8978cf100:/accessify#pytest-vvtestsClean container and images with the following command:$dockerrm$(dockerps-a-q)-f
$dockerrmi$(dockerimages-q)-fWhen you will make changes, ensure your code passthe checkersand is covered by tests usingpytest.If you are new for the contribution, please read:Read about pull requests —https://help.github.com/en/articles/about-pull-requestsRead how to provide pull request —https://help.github.com/en/articles/creating-a-pull-request-from-a-forkAlso the useful article about how to contribute —https://akrabat.com/the-beginners-guide-to-contributing-to-a-github-project/ReferencesCheck it out to familiarize yourself with class members accessibility levels:C# accessibility levels —https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/accessibility-levelsJava accessibility levels —https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.htmlObject-oriented programming interfaces —https://www.cs.utah.edu/~germain/PPS/Topics/interfaces.htmlInterfaces in C# —https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/interfaceInterfaces in Java —https://docs.oracle.com/javase/tutorial/java/concepts/interface.html