https://github.com/tybruno/base-descriptor
A simple, fast, typed, and tested abstract and base classes for a python3.6+ Non Data Descriptor, Data Descriptor, and Slottable Data Descriptor.
https://github.com/tybruno/base-descriptor
data-descriptor data-descriptors descriptor non-data-descriptor slottable-data-descriptor
Last synced: 4 months ago
JSON representation
A simple, fast, typed, and tested abstract and base classes for a python3.6+ Non Data Descriptor, Data Descriptor, and Slottable Data Descriptor.
- Host: GitHub
- URL: https://github.com/tybruno/base-descriptor
- Owner: tybruno
- License: mit
- Created: 2023-08-25T17:03:39.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2025-09-23T21:07:31.000Z (8 months ago)
- Last Synced: 2026-01-03T00:20:52.011Z (5 months ago)
- Topics: data-descriptor, data-descriptors, descriptor, non-data-descriptor, slottable-data-descriptor
- Language: Python
- Homepage: https://pypi.org/project/base-descriptor/
- Size: 30.3 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://GitHub.com/Naereen/StrapDown.js/graphs/commit-activity)
[](https://opensource.org/licenses/MIT)
[](https://codecov.io/gh/tybruno/descriptor)
# base-descriptor
A simple, fast, typed, and tested abstract and base classes for a python3.6+
Non Data Descriptor, Data Descriptor, and Slottable Data Descriptor. The goal
is to
aid in the creation of descriptors allowing other developers to make
descriptors for their own use case.
#### Key Features:
* **Easy**: Flexable and easy to inherit the prebuilt Non Data Descriptors,
Data Descriptors, and Slottable Data Descriptors to create your own
descriptors.
* **Great Developer Experience**: Being fully typed makes it great for editor
support.
* **Fully Tested**: Our test suit fully tests the functionality to ensure that
all of the classes in this module run as expected.
## Installation
`pip install base-descriptor`
## Table of Contents
- [Objects Provided in this Module](#objects-provided-in-this-module)
- [Non Data Descriptors](#non-data-descriptors)
- [Data Descriptors](#data-descriptors)
- [Slottable Data Descriptors](#slottable-data-descriptors)
- [Non Data Descriptor Examples](#non-data-descriptor-examples)
- [AbstractNonDataDescriptor](#abstractnondatadescriptor)
- [Data Descriptor Examples](#data-descriptor-examples)
- [ReadOnly](#readonly)
- [DefaultDescriptor](#defaultdescriptor)
- [BaseDataDescriptor](#basedatadescriptor)
- [AbstractDataDescriptor](#abstractdatadescriptor)
- [Slottable Data Descriptors](#slottable-data-descriptors-1)
- [SlottableDefaultDescriptor](#slottabledefaultdescriptor)
- [BaseSlottableDataDescriptor](#baseslottabledatadescriptor)
- [References](#references)
## Objects Provided in this Module
### Non Data Descriptors
A non-data descriptor in Python is a type of descriptor that only implements
the `__get__()` method. Descriptors are a way to customize attribute access in
Python. When an attribute is
accessed on an object, Python checks if a descriptor exists for that attribute
in the class or its ancestors. If found, the descriptor's `__get__()` method is
called to determine the final
value of the attribute.
| Class | Description |
|-----------------------------|--------------------------------------------------------|
| `AbstractNonDataDescriptor` | Abstract Base Class for creating Non Data Descriptors. |
### Data Descriptors
A data descriptor in Python is a type of descriptor that implements
both `__get__()` and either `__set__()` or `__delete__()`. Data descriptors
allow you to define custom behavior for
attribute
access, including setting or deleting the attribute in addition to retrieving
its value.
| Class | Description |
|--------------------------|----------------------------------------------------------------------------------------------------|
| `AbstractDataDescriptor` | Abstract Base Class for creating Data Descriptors. |
| `BaseDataDescriptor` | Base Class for creating Data Descriptors. Provides the same functionality as a standard attribute. |
| `DefaultDescriptor` | A Data Descriptor that has a default value. |
| `ReadOnly` | A Data Descriptor that is read only. |
### Slottable Data Descriptors
A Data Descriptor that plays well with `__slots__`. This module was inspired by
Dr. Fred Baptiste [fbaptiste](https://github.com/fbaptiste).
The slottable data descriptor has the following advantages:
1. Has instance specific storage
2. Does not use the instance for storage, thus works with __slots__.
`__slots__ = "__weakref__"` must be set.
3. Handles non hashable instances
4. Data storage is clean.
| Class | Description |
|-----------------------------------|--------------------------------------------------------------------------------------------------------------|
| `AbstractSlottableDataDescriptor` | Abstract Base Class for creating Slottable Data Descriptors. |
| `BaseSlottableDataDescriptor` | Base Class for creating Slottable Data Descriptors. Provides the same functionality as a standard attribute. |
| `SlottableDefaultDescriptor` | A Slottable Data Descriptor that has a default value. |
## Non Data Descriptor Examples
### `AbstractNonDataDescriptor`
Simple way to Inherit from `AbstractNonDataDescriptor` to create your own Non
Data Descriptor.
```python
from base_descriptor import AbstractNonDataDescriptor
class SquareDescriptor(AbstractNonDataDescriptor):
def __get__(self, instance, owner=None):
if instance is None:
# Access through the class, return the descriptor itself
return self
return instance._value ** 2
class MyClass:
square = SquareDescriptor()
def __init__(self, value):
self._value = value
# Create an instance of MyClass
my_instance = MyClass(5)
# Access the square attribute using the descriptor
# This will calculate and return the square
print(my_instance.square) # 25
```
## Data Descriptor Examples
### `ReadOnly`
```python
from base_descriptor import ReadOnly
class Person:
name = ReadOnly("Guido")
person = Person()
print(person.name) # Guido
person.name = "Raymond" # raises AttributeError
```
### `DefaultDescriptor`
Default Descriptor that provides a default value for the attribute.
```python
from base_descriptor import DefaultDescriptor
class Person:
name = DefaultDescriptor(default="Guido")
print(Person.name) #
person = Person()
print(person.name) # Guido
person.name = "Raymond"
print(person.name) # Raymond
```
### `BaseDataDescriptor`
Provides the same functionality as a standard attribute.
It enables you to create your own Data Descriptor by overriding
the `__set_name__()`, `__set__()`, `__get__()`,
or `__delete__()` methods to match your requirements.
```python
from base_descriptor import BaseDataDescriptor
class Plus2(BaseDataDescriptor):
def __set__(self, instance, value):
value = value + 2
instance.__dict__[self._property_name] = value
class Foo:
bar = Plus2()
foo = Foo()
foo.bar = 1
print(foo.bar) # 3
```
### `AbstractDataDescriptor`
Provides an Abstract Base Class that can be inherited from to help create your
own Data Descriptors.
```python
from base_descriptor import AbstractDataDescriptor
class MyDataDescriptor(AbstractDataDescriptor):
def __init__(self):
self._value = None
def __get__(self, instance, owner):
return self._value
def __set__(self, instance, value):
self._value = value
def __delete__(self, instance):
self._value = None
class MyClass:
my_data_descriptor = MyDataDescriptor()
obj = MyClass()
obj.my_data_descriptor = 1
print(obj.my_data_descriptor) # 1
```
## Slottable Data Descriptors
### `SlottableDefaultDescriptor`
Slottable Default Descriptor that provides a default value for the attribute.
```python
from base_descriptor import SlottableDefaultDescriptor
class Person:
__slots__ = "__weakref__"
first_name = SlottableDefaultDescriptor(default="Guido")
person = Person()
print(person.first_name) # Guido
person.first_name = "Raymond"
print(person.first_name) # Raymond
```
### `BaseSlottableDataDescriptor`
Provides the same functionality as a standard attribute.
It enables you to create your own Slottable Data Descriptor by overriding
the `__set_name__()`, `__set__()`, `__get__()`,
or `__delete__()` methods to match your requirements.
```python
from base_descriptor import BaseSlottableDataDescriptor
class MyDescriptor(BaseSlottableDataDescriptor):
def __set__(self, instance, value):
print(f"Setting {self._property_name} to {value}")
instance.__dict__[self._property_name] = value
class Foo:
__slots__ = "__weakref__"
bar = MyDescriptor()
foo = Foo()
foo.bar = 1
print(foo.bar) # 1
```
## References
This module was heavily inspired by the following resources:
1. **Python Deep Dive: Part 4**
- Author: Dr. Fred Baptiste ([fbaptiste](https://github.com/fbaptiste))
- Year: 2023
- Course
Title: [Python Deep Dive: Part 4](https://www.udemy.com/course/python-3-deep-dive-part-4/)
- Platform: Udemy
2. **Descriptor HowTo Guide**
- Source: Python Documentation
- URL:
[Descriptor HowTo Guide](https://docs.python.org/3/howto/descriptor.html)