Metadata-Version: 2.1
Name: python-access-modifiers
Version: 1.2.1
Summary: Python decorators to specify accessible scopes and enhance access control of methods.
Author: mxngo
License-File: LICENSE
Classifier: Development Status :: 5 - Production/Stable
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Utilities
Requires-Python: >=3.12
Description-Content-Type: text/markdown

![Version]
![SupportedVersions]
![License]

[Version]: https://img.shields.io/pypi/v/python-access-modifiers
[SupportedVersions]: https://img.shields.io/badge/python-3.12-orange
[License]: https://img.shields.io/badge/license-MIT-yellow

# Installation
Built and tested on Python 3.12.<br>
No requirements other than the module itself.
```py
pip install python-access-modifiers
```
# Introduction
`python-access-modifiers` is a lightweight Python package designed to enhance access control of methods within classes and modules.

### Decorators
`@private` - Allows you to designate methods as "private", controlling the accessibility of the method based on the calling context.<br>
`@protected` - Allows for the creation of "protected" methods, allowing access from within the defining class and any classes that inherit from it.

# Example Usage
### Creating a private method inside of a class
```py
from python_access_modifiers import private

class MyClass():
    @private
    def my_private_method(self) -> None:
        print("This is a private method")

    def my_public_method(self) -> None:
        print("This is a public method")
        self.my_private_method()

my_class = MyClass()
my_class.my_public_method()
```
### Output
No exception is raised because `my_private_method` is called from within `MyClass`, not from outside of the accessible scope.
```
This is a public method
This is a private method
```
### Calling a private method outside of the accessible scope
```py
from python_access_modifiers import private

class MyClass():
    @private
    def my_private_method(self) -> None:
        print("This is a private method")

    def my_public_method(self) -> None:
        print("This is a public method")
        self.my_private_method()

my_class = MyClass()
my_class.my_private_method()
```
### Output
```
RuntimeError: Cannot invoke private method "MyClass.my_private_method" from within the scope of "__main__"
```
### Creating classes that inherit private methods
```py
from python_access_modifiers import private

class Base():
    @private
    def my_private_method(self):
        print("This is a private method")

    def my_public_method(self):
        print("This is a public method")
        self.my_private_method()

class Child(Base):
    ...

child = Child()
child.my_public_method()
```
### Output
`my_private_method` is called from within the `Base` class, therefore no exception is raised.
```
This is a public method
This is a private method
```
However, if `my_private_method` was called directly from outside of the accessible scope of the `Base` class, a `RuntimeError` would be raised.
```py
child = Child()
child.my_private_method()
```
### Output
```
RuntimeError: Cannot invoke private method "Base.my_private_method" from within the scope of "__main__"
```
### Creating a private method from inside of a module
`my_module.py`
```py
from python_access_modifiers import private

@private
def my_private_method():
    print("This method is private to my_module")
```
`main.py`
```py
from my_module import my_private_method

my_private_method()
```
### Output
```
RuntimeError: Cannot invoke private method "my_module.my_private_method" from module "__main__"
```
# Creating a protected method
```py
from python_access_modifiers import protected

class MyBaseClass():
    @protected
    def my_protected_method(self):
        print("This method is protected inside of MyBaseClass")

    def call_protected_method(self):
        self.my_protected_method()

class MySubClass(MyBaseClass):
    def call_protected_method_from_subclass(self):
        self.my_protected_method()
        
subclass = MySubClass()

subclass.call_protected_method()
subclass.call_protected_method_from_subclass()
```
### Output
If `my_protected_method` is called from within `MyBaseClass` or from within one of it's subclasses (i.e: `MySubClass`), the method gets called normally.
```
This method is protected inside of MyBaseClass
This method is protected inside of MyBaseClass
```
However, if `my_protected_method` is called from outside of the accessible scope of the base class and it's subclasses, an exception will be raised.
```py
subclass.my_protected_method()
```
### Output
```
RuntimeError: Cannot invoke protected method "MyBaseClass.my_protected_method" from within the scope of "__main__"
```