A kit containing tools for better programming.
Project description
Overview
modkit is a collection of tools that can be used for better programming
experience and automation.
Features
@overridedecorator for python3.8+- New
Propertyclass that automates property definition and takes less number of lines of code to define. - New
Possibilityclass that helps extend return types with custom methods/properties which in turn helps in better readability of code.
Usage
-
@overridedecorator and functionality.The
@overridedecorator was introduced in python3.12+ under thetypingmodule. However, for python<3.12, it is not available.The
overrideclass undermodkitsupports python3.8+ and brings additional features rather than just helping in maintaining an error free codebase.The
overrideclass contains two static methods that can be used as decorators:clsandmtd. The@override.mtdacts as a decorator for the child class methods which are being over-ridden from the parent class. It sets the__override__attribute of the methods, it has been decorated with, asTrue.The
@override.clsdecorator on top of a child class, checks for all methods that have their__override__attribute set asTrueand it generates errors accordingly. It will raiseMethodOverrideErrorif the method set as override is not present in the parent class. Additionally, it will also check if the current class is a child class or not (inheritance is implemented or not).Apart from methods, the properties need not be decorated with
mtd, the@override.clsover the class will automatically check if the property is over-ridden or not. If a over-ridden property does not include asetterordeleteror both, the parent property'ssetteranddeleterwill be copied to the child class.Use case
-
Import the
overrideclass frommodkit.typingfrom modkit.typing import override
-
Define a Base Class.
class Base: def __init__(self) -> None: self.value = 10 def base_method(self) -> None: self.value += 1 @property def base_property(self) -> int: return self.value @base_property.setter def base_property(self, value) -> None: self.value = value @base_property.deleter def base_property(self) -> None: self.value = 0
-
Define the Child Class with
overrideclass.@override.cls # valid class Child(Base): @override.mtd # valid def base_method(self, incrementor: int) -> None self.value += incrementor @property # valid def base_property(self) -> int: return self.value + 10 # since no setter, deleter are set, # it will use parent's setter and deleter. @override.mtd # invalid, not present in base class. def child_method(self) -> str: return str(self.value)
-
The
look_inclassmethod ofoverrideclass.The
overrideclass checks for methods and properties present in the child class with respect to the recent parent of the child. However, this behavior can be changed to check for the topmost base class (not object).Example:
override.look_in('topmost') # other values: `recent` class Top: def top_method(self) -> None: pass @override.cls class Mid(Top): @override.mtd # valid def top_method(self) -> str: pass def mid_method(self) -> None: pass @override.cls class Bottom(Mid): @override.mtd # invalid, mid_method is present in mid, # and not in the top most base class that is Top def mid_method(self) -> str: pass @override.mtd # valid def top_method(self) -> int: pass
To avoid conflicts in most cases, use the default setting, or go back to the default setting using
override.look_in('recent').
-
-
Propertyclass for automatingpropertycreation.Usage Warning:
Propertyclass internally usespropertyto maintain, create and dispatch propertygetter,setteranddeleter, however, it does not support static type checking as this an external class.The
Propertyclass can be used to quickly and neatly define properties of a class.-
By binding an attribute.
The
propertyclass can be used to create a property that is bound to an attribute, with easysetteranddeletercreation or blocking.from modkit.classtools import Property class Example: def __init__(self, value: int) -> None: self._value = value # note that, this is the only way the Property can be defined, # it cannot be defined inside a method, or another property. value = Property( attribute='_value', # bind to _value, setter=True, # enable setter, deleter=True, # enable deleter, deleter_deletes_attribute=False, # this prevents the deleter from actually deleting the # attribute (del self._value). Instead, it sets self._value # to None. # However, if deleter_deletes_attribute is set to True, # the _value attribute will be deleted. )
It also supports blocking
setterordeleteror both.from modkit.classtools import Property class Example2: def __init__(self, value: int) -> None: self._value = value value = Property( attribute='_value', # bind to _value, setter=False, # block setting it, deleter=False, # block deletion, error=AttributeError, # choose any exception to raise, # any custom exception can also be used. # as long as it is a child class of Exception or Exception # itself, setter_error_arguments=("Cannot set _value",), # choose setter error arguments for the exception. deleter_error_arguments-("Cannot delete _value",), # choose deleter error arguments for the exception. ) # This property can only be accessed and cannot be set or # deleted. Trying to do the same will raise AttributeError.
-
By explicitly defining
getter,setter, anddeleter.from modkit.classtools import Property class Example3: def __init__(self, value: int) -> None: self._value = value value_is_none = Property( getter=lambda cls: cls._value is None, # returns bool. setter=None, # blocking setter, or define it just like getter. deleter=None, # blocking deleter. error=ValueError, # set, delete will raise ValueError, setter_error_arguments=("Read-only property.",), deleter_error_arguments=("Read-only property.",), ) # This will create a property named value_is_none which returns # bool, based on _value. # using previously defined property. value_is_not_none = Property( getter=lambda cls: not cls.value_is_none, setter=None, deleter=None, error=AttributeError, setter_error_arguments=("Read-only.",), deleter_error_arguments=("Read-only.",), ) # creating with setter and deleter. value = Property( getter=lambda cls: cls._value, setter=lambda cls, value: setattr(cls, '_value', value), deleter=lambda cls: setattr(cls, '_value', None), )
-
-
The
Possibilityclass to extend return types functionality.Suppose there is a function that returns an
intand that is it for that, it cannot do anything else.I wanted to check if the
intvalue returned is a positive number or negative. A normal code will do it like this:# a function that returns an int def func() -> int: return 10
# checking positive or negative >>> func() > 0 True
The
Possibilityway:-
Import the
Possibilityabstract class.from modkit.classtools import Possibility
-
Create a new return type, say,
Extra.class Extra(Possibility): # leave the __init__ method untouched. # The Possibility class has three properties # parent, attribute (attribute_name) # and value (attribute's value). # __bool__ method needs to be defined (as it is an # abstract method.), we will do it later. # let us create a method named, is_positive. def is_positive(self) -> bool: return self.value >= 0 # the __bool__ method def __bool__(self) -> bool: return self.value is not None # this implements the `if <class-here>` statement # so u can set any logic here.
-
Modify the Function.
# The __init__ method of Extra will take 3 parameters. # parent: the parent class. # attribute: The attribute name # value: The value. # for now, we will leave, parent, and attribute. def func() -> Extra[int]: return Extra(parent=None, attribute='', value=10)
-
Assess the result.
>>> func() # will return Extra <Extra object at XXXXXXX> >>> func().is_positive() # if the value is positive. True >>> func()() # get the value. 10
-
Using in a class.
We will use the
Extraclass we created above.class Example: def __init__(self, value: int) -> None: self._value = value @property def value(self) -> Extra[int]: return Extra( parent=self, attribute='_value', value=self._value )
Let us see the results.
>>> obj = Example(100) >>> obj.value # simply using this will return the Extra class object <Extra object at XXXXXX> >>> obj.value() # even though it is a property, () calling it will return the value 100 # if it was a method, you have to call it twice, like value()(). >>> obj.value.is_positive() # better readability. True
-
Contributing
Contributions are welcome, create and issue here and create a pull request here.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file modkit-1.3.0.tar.gz.
File metadata
- Download URL: modkit-1.3.0.tar.gz
- Upload date:
- Size: 15.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8504f56a1b2f83d83dd00ed44f86eab86ba89d38354bbc71d7d664f7f8b8c00b
|
|
| MD5 |
e3c835f0bad8e5e9d7c06ebd9b32dceb
|
|
| BLAKE2b-256 |
fdba3f480e76dbf1b958953a84dd5cc5d2be76e25f88bc219f48df6592e157d3
|
File details
Details for the file modkit-1.3.0-py3-none-any.whl.
File metadata
- Download URL: modkit-1.3.0-py3-none-any.whl
- Upload date:
- Size: 15.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c197f34d9b9bb50fd4904b52ed58ed7a87e04822a5dc987562e709475875c911
|
|
| MD5 |
f4927e4cccc863e957353c2df85f5cfb
|
|
| BLAKE2b-256 |
09e68662ae89bd424d805771d56ed83c70d61e592cb90332730e3ec1573c5aaf
|