Skip to main content

Allows ORM constructs to be sealed to prevent them from executing queries on attribute accesses.

Project description

Seal
Build Status Coverage status

Django application providing queryset sealing capability to force appropriate usage of only()/defer() and select_related()/prefetch_related().

Installation

pip install django-seal

Usage

# models.py
from django.db import models
from seal.models import SealableModel

class Location(SealableModel):
    latitude = models.FloatField()
    longitude = models.FloatField()

class SeaLion(SealableModel):
    height = models.PositiveIntegerField()
    weight = models.PositiveIntegerField()
    location = models.ForeignKey(Location, models.CASCADE, null=True)
    previous_locations = models.ManyToManyField(Location, related_name='previous_visitors')

By default UnsealedAttributeAccess warnings will be raised on sealed objects attributes accesses

>>> location = Location.objects.create(latitude=51.585474, longitude=156.634331)
>>> sealion = SeaLion.objects.create(height=1, weight=100, location=location)
>>> sealion.previous_locations.add(location)
>>> SeaLion.objects.only('height').seal().get().weight
UnsealedAttributeAccess:: Attempt to fetch deferred field "weight" on sealed <SeaLion instance>.
>>> SeaLion.objects.seal().get().location
UnsealedAttributeAccess: Attempt to fetch related field "location" on sealed <SeaLion instance>.
>>> SeaLion.objects.seal().get().previous_locations.all()
UnsealedAttributeAccess: Attempt to fetch many-to-many field "previous_locations" on sealed <SeaLion instance>.

You can elevate the warnings to exceptions by filtering them. This is useful to assert no unsealed attribute accesses are performed when running your test suite for example.

>>> import warnings
>>> from seal.exceptions import UnsealedAttributeAccess
>>> warnings.filterwarnings('error', category=UnsealedAttributeAccess)
>>> SeaLion.objects.only('height').seal().get().weight
Traceback (most recent call last)
...
UnsealedAttributeAccess:: Attempt to fetch deferred field "weight" on sealed <SeaLion instance>.
>>> SeaLion.objects.seal().get().location
Traceback (most recent call last)
...
UnsealedAttributeAccess: Attempt to fetch related field "location" on sealed <SeaLion instance>.
>>> SeaLion.objects.seal().get().previous_locations.all()
Traceback (most recent call last)
...
UnsealedAttributeAccess: Attempt to fetch many-to-many field "previous_locations" on sealed <SeaLion instance>.

Or you can configure logging to capture warnings to log unsealed attribute accesses to the py.warnings logger which is a nice way to identify and address unsealed attributes accesses from production logs without taking your application down if some instances happen to slip through your battery of tests.

>>> import logging
>>> logging.captureWarnings(True)

Sealable managers can also be automatically sealed at model definition time to avoid having to call seal() systematically by passing seal=True to SealableModel subclasses, SealableManager and SealableQuerySet.as_manager.

from django.db import models
from seal.models import SealableManager, SealableModel, SealableQuerySet

class Location(SealableModel, seal=True):
    latitude = models.FloatField()
    longitude = models.FloatField()

class SeaLion(SealableModel):
    height = models.PositiveIntegerField()
    weight = models.PositiveIntegerField()
    location = models.ForeignKey(Location, models.CASCADE, null=True)
    previous_locations = models.ManyToManyField(Location, related_name='previous_visitors')

    objects = SealableManager(seal=True)
    others = SealableQuerySet.as_manager(seal=True)

Development

Make your changes, and then run tests via tox:

tox

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django-seal-1.6.1.tar.gz (12.2 kB view details)

Uploaded Source

Built Distribution

django_seal-1.6.1-py2.py3-none-any.whl (9.1 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file django-seal-1.6.1.tar.gz.

File metadata

  • Download URL: django-seal-1.6.1.tar.gz
  • Upload date:
  • Size: 12.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.5

File hashes

Hashes for django-seal-1.6.1.tar.gz
Algorithm Hash digest
SHA256 21af9495127dbf51e8ab567ac5a96fff76e43a5df4e46356ded7df8ca4fe6324
MD5 2c447e97a23701416f46041d17a20448
BLAKE2b-256 6713dc72299b4438231447c839497d76ece5cd1e8f794a92d4c773c6e1befaf1

See more details on using hashes here.

File details

Details for the file django_seal-1.6.1-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for django_seal-1.6.1-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 75b0236f0dd12a1aa92dcf50fa00c8ac855f21148837bc8d6d242fd6233ada9a
MD5 b75b9ad1fa1a0d149074f1bc12d346cf
BLAKE2b-256 4ca7c7bfe50e3bb2fe105cf46af20db229e16826ddb9b1c8a10f6d02bcfbee0f

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page