Skip to main content
https://img.shields.io/pypi/v/fallback-property.svg Build Status https://coveralls.io/repos/github/jonasundderwolf/fallback-property/badge.svg?branch=master https://img.shields.io/pypi/pyversions/fallback-property.svg

Requirements

  • Python 3.6+

What is it?

fallback_property transforms a function into a property and uses the decorated function as fallback if no value was assigned to the property itself. A special descriptor (fallback_property.FallbackDescriptor) is used internally.

Django (or similar frameworks)

fallback_property is useful if you have a function that aggregates values from related objects, which could already be fetched using an annotated queryset. The decorator will favor the precalculated value over calling the actual method.

It is especially helpful, if you optimize your application and want to replace legacy or performance critical properties with precalulated values using .annotate().

How to use it?

Simply define a function and use the decorator fallback_property

from fallback_property import fallback_property

class Foo:

    @fallback_property()
    def fallback_func(self):
        return 7

Arguments

The fallback_property() has two optional arguments.

cached: bool = True

If the property is accessed multiple times, call the fallback function only once.

logging: bool = False

Log a warning if there was a fallback to the decorated, original method.

Usage Example (Django)

Suppose we have the following models

from django.db import models


class Pipeline(model.Model):
    @property
    def total_length(self):
        return sum(self.parts.values_list('length', flat=True))


class Parts(models.Model):
    length = models.PositiveIntegerField()
    pipeline = models.ForeignKey(Pipeline, related_name='parts')

Calling pipline.total_length will always trigger another query and is even more expensive when dealing with multiple objects. This can be optimized by using .annotate() and fallback_property()

from django.db import models, QuerySet
from django.db.functions import Coalesce
from django.db.models import Sum
from fallback_property import fallback_property


class PipelineQuerySet(QuerySet):

    def with_total_length(self):
        return self.annotate(
            total_length=Coalesce(
                Sum('parts__length', output_field=models.IntegerField()),
                0,
            )
        )


class Pipeline(model.Model):

    @fallback_property(logging=True)
    def total_length(self):
        return sum(self.parts.values_list('length', flat=True))

You can now access the total_length without triggering another query or get a warning, when the fallback function is used

pipeline = Pipeline.objects.with_total_length().first()
print(pipeline.total_length)

Important: The annotated value and the property must have the same name.

Development

This project is using poetry to manage all dev dependencies.

Clone this repository and run

poetry install
poetry run pip install django

to create a virtual environment with all dependencies.

You can now run the test suite using

poetry run pytest

This repository follows the angular commit conventions. You can register a pre-commit hook to validate your commit messages by using husky. The configurations are already in place if you have nodejs installed. Just run

npm install

and the pre-commit hook will be registered.

Metadata

Release files for fallback-property 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fallback-property 0.2.0
File Size Uploaded
fallback-property-0.2.0.tar.gz 6.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fallback-property 0.2.0
File Interpreter ABI Platform
fallback_property-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 11.6 kB

Release files / fallback-property-0.2.0.tar.gz

Download URL fallback-property-0.2.0.tar.gz
Size 6.0 kB
Tags Source
SHA-256 checksum
How to use checksums
d38ade19054561af1ff1a75d31039f5433dc69a6f0dab575f4325f6cf3309a9e
BLAKE2b-256 checksum
How to use checksums
ac6869bf9263c237af25f1c9a72a6f81e5faee98190820d96f5d3149b724f328
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.8.2

Release files / fallback_property-0.2.0-py3-none-any.whl

Download URL fallback_property-0.2.0-py3-none-any.whl
Size 5.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
81df40929c17b1d5520e1a168cf28c926240a17f51455a7144d78d4689bfe786
BLAKE2b-256 checksum
How to use checksums
bb862df9de9c7c44472c1afa9d47638e1da14cdbd1e018c7f9c27f614bd8c72d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.8.2

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page