Metadata-Version: 1.1
Name: django-seal
Version: 1.4.2
Summary: Allows ORM constructs to be sealed to prevent them from executing queries on attribute accesses.
Home-page: https://github.com/charettes/django-seal
Author: Simon Charette
Author-email: simon.charette@zapier.com
License: MIT License
Description: django-seal
        ===========
        
        .. image:: https://publicdomainvectors.org/photos/Seal2.png
            :target: https://publicdomainvectors.org
            :alt: Seal
        
        ------------
        
        .. image:: https://github.com/charettes/django-seal/workflows/Test/badge.svg
            :target: https://github.com/charettes/django-seal/actions
            :alt: Build Status
        
        .. image:: https://coveralls.io/repos/github/charettes/django-seal/badge.svg?branch=master
            :target: https://coveralls.io/github/charettes/django-seal?branch=master
            :alt: Coverage status
        
        
        Django application providing queryset sealing capability to force appropriate usage of ``only()``/``defer()`` and
        ``select_related()``/``prefetch_related()``.
        
        Installation
        ------------
        
        .. code:: sh
        
            pip install django-seal
        
        Usage
        -----
        
        .. code:: python
        
            # 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
        
        .. code:: python
        
            >>> 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.
        
        .. code:: python
        
            >>> 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.
        
        .. code:: python
        
            >>> import logging
            >>> logging.captureWarnings()
        
        .. _elevate the warnings to exceptions by filtering them: https://docs.python.org/3/library/warnings.html#warnings.filterwarnings
        .. _configure logging to capture warnings: https://docs.python.org/3/library/logging.html#logging.captureWarnings
        
        Development
        -----------
        
        Make your changes, and then run tests via tox:
        
        .. code:: sh
        
            tox
        
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Framework :: Django :: 2.2
Classifier: Framework :: Django :: 3.0
Classifier: Framework :: Django :: 3.1
Classifier: Framework :: Django :: 3.2
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Topic :: Software Development :: Libraries :: Python Modules
