<commit_before>import logging
import warnings

from django.db.models import signals
from django.core.exceptions import ImproperlyConfigured

from .models import URLChangeRecord
from .mixins import URLTrackingMixin

logger = logging.getLogger(__file__)


class URLTrackingError(Exception):
    """
    Exception raised when an error occures during URL tracking.
    """
    pass


def lookup_previous_url(instance, **kwargs):
    """
    Look up the absolute URL of *instance* from the database while it is
    in a ``pre_save`` state. The previous urls are saved in the instance's
    *_old_urls* attribute as dictionary. The method name for the given URLs
    are used as the dictionary keys.

    If the instance has not been saved to the database (i.e. is new)
    the ``_old_urls`` dictionary is set to ``{}`` which will prevent a record
    to be created.
    """
    try:
        db_instance = instance.__class__.objects.get(pk=instance.pk)
        logger.debug("saving old URL for instance '%s' URL",
                     instance.__class__.__name__)
    except instance.__class__.DoesNotExist:
        logger.debug("new instance, no URL tracking required")
        instance._old_urls = {}
        return

    for method_name in instance.get_url_tracking_methods():
        try:
            method = getattr(db_instance, method_name)
        except AttributeError:
            raise ImproperlyConfigured(
                "model instance '%s' does not have a method '%s'" % (
                    db_instance.__class__.__name__,
                    method_name
                )
            )
        instance._old_urls[method_name] = method()


def _create_delete_record(url):
    """
    Create a delete record for the given *url*. This updates all records
    where *url* is the ``new_url`` (previous redirects). It also creates
    a new record with *url* being the ``old_url`` and no ``new_url`` and
    marked as deleted. This marks an endpoint in the chain of URL
    redirects.
    """
    # updated existing records with the old URL being the new_url
    # of this record. Changed the *deleted* flag to be ``False``
    url_records = URLChangeRecord.objects.filter(new_url=url).update(
        new_url='',
        deleted=True
    )

    record, created = URLChangeRecord.objects.get_or_create(old_url=url)
    record.deleted = True
    record.save()


def track_changed_url(instance, **kwargs):
    """
    Track a URL changes for *instance* after a new instance was saved. If
    no old URLs are available (i.e. *instance* is new) or if a new and old URL
    are the same (i.e. URL is unchanged), nothing will be changed in the
    database for this URL.

    For URLs that have changed, the database will be checked for existing
    records that have a *new_url* entry equal to the old URL of *instance* and
    updates these records. Then, a new ``URLChangeRecord`` is created for this
    URL.
    """
    for method_name, old_url in getattr(instance, '_old_urls', {}).items():
        try:
            new_url = getattr(instance, method_name)()
        except AttributeError:
            continue

        # if the new URL is None we assume that it has been deleted and
        # create a delete record for the old URL.
        if new_url is None:
            _create_delete_record(old_url)
            continue

        # we don't want to store URL changes for unchanged URL
        if old_url is None or old_url == new_url:
            continue

        logger.debug(
            "tracking URL change for instance '%s' URL",
            instance.__class__.__name__
        )

        # check if the new URL is already in the table and
        # remove these entries
        URLChangeRecord.objects.filter(old_url=new_url).delete()

        # updated existing records with the old URL being
        # the new URL in the record
        url_records = URLChangeRecord.objects.filter(new_url=old_url).update(
            new_url=new_url,
            deleted=False
        )

        # create a new/updated record for this combination of old and
        # new URL. If the record already exists, it is assumed that the
        # current change is to be used and the existing new_url will be
        # detached from the old_url.

        record, created = URLChangeRecord.objects.get_or_create(old_url=old_url)
        record.new_url = new_url
        record.deleted = False
        record.save()

def track_deleted_url(instance, **kwargs):
    """
    Track the URL of a deleted *instance*. It updates all existing
    records with ``new_url`` being set to the *instance*'s old URL and
    marks this record as deleted URL.

    A new ``URLChangeRecord`` is created for the old URL of *instance*
    that is marked as deleted.
    """
    logger.debug("tracking deleted instance '%s' URL",
                 instance.__class__.__name__)<commit_msg>Remove unused variables<commit_after>import logging
import warnings

from django.db.models import signals
from django.core.exceptions import ImproperlyConfigured

from .models import URLChangeRecord
from .mixins import URLTrackingMixin

logger = logging.getLogger(__file__)


class URLTrackingError(Exception):
    """
    Exception raised when an error occures during URL tracking.
    """
    pass


def lookup_previous_url(instance, **kwargs):
    """
    Look up the absolute URL of *instance* from the database while it is
    in a ``pre_save`` state. The previous urls are saved in the instance's
    *_old_urls* attribute as dictionary. The method name for the given URLs
    are used as the dictionary keys.

    If the instance has not been saved to the database (i.e. is new)
    the ``_old_urls`` dictionary is set to ``{}`` which will prevent a record
    to be created.
    """
    try:
        db_instance = instance.__class__.objects.get(pk=instance.pk)
        logger.debug("saving old URL for instance '%s' URL",
                     instance.__class__.__name__)
    except instance.__class__.DoesNotExist:
        logger.debug("new instance, no URL tracking required")
        instance._old_urls = {}
        return

    for method_name in instance.get_url_tracking_methods():
        try:
            method = getattr(db_instance, method_name)
        except AttributeError:
            raise ImproperlyConfigured(
                "model instance '%s' does not have a method '%s'" % (
                    db_instance.__class__.__name__,
                    method_name
                )
            )
        instance._old_urls[method_name] = method()


def _create_delete_record(url):
    """
    Create a delete record for the given *url*. This updates all records
    where *url* is the ``new_url`` (previous redirects). It also creates
    a new record with *url* being the ``old_url`` and no ``new_url`` and
    marked as deleted. This marks an endpoint in the chain of URL
    redirects.
    """
    # updated existing records with the old URL being the new_url
    # of this record. Changed the *deleted* flag to be ``False``
    URLChangeRecord.objects.filter(new_url=url).update(
        new_url='',
        deleted=True
    )

    record, __ = URLChangeRecord.objects.get_or_create(old_url=url)
    record.deleted = True
    record.save()


def track_changed_url(instance, **kwargs):
    """
    Track a URL changes for *instance* after a new instance was saved. If
    no old URLs are available (i.e. *instance* is new) or if a new and old URL
    are the same (i.e. URL is unchanged), nothing will be changed in the
    database for this URL.

    For URLs that have changed, the database will be checked for existing
    records that have a *new_url* entry equal to the old URL of *instance* and
    updates these records. Then, a new ``URLChangeRecord`` is created for this
    URL.
    """
    for method_name, old_url in getattr(instance, '_old_urls', {}).items():
        try:
            new_url = getattr(instance, method_name)()
        except AttributeError:
            continue

        # if the new URL is None we assume that it has been deleted and
        # create a delete record for the old URL.
        if new_url is None:
            _create_delete_record(old_url)
            continue

        # we don't want to store URL changes for unchanged URL
        if old_url is None or old_url == new_url:
            continue

        logger.debug(
            "tracking URL change for instance '%s' URL",
            instance.__class__.__name__
        )

        # check if the new URL is already in the table and
        # remove these entries
        URLChangeRecord.objects.filter(old_url=new_url).delete()

        # updated existing records with the old URL being
        # the new URL in the record
        url_records = URLChangeRecord.objects.filter(new_url=old_url).update(
            new_url=new_url,
            deleted=False
        )

        # create a new/updated record for this combination of old and
        # new URL. If the record already exists, it is assumed that the
        # current change is to be used and the existing new_url will be
        # detached from the old_url.

        record, __ = URLChangeRecord.objects.get_or_create(old_url=old_url)
        record.new_url = new_url
        record.deleted = False
        record.save()

def track_deleted_url(instance, **kwargs):
    """
    Track the URL of a deleted *instance*. It updates all existing
    records with ``new_url`` being set to the *instance*'s old URL and
    marks this record as deleted URL.

    A new ``URLChangeRecord`` is created for the old URL of *instance*
    that is marked as deleted.
    """
    logger.debug("tracking deleted instance '%s' URL",
                 instance.__class__.__name__)
{'fraction_non_alphanumeric': 0.0748712667353244, 'fraction_numerical': 0.0, 'mean_word_length': 2.507042253521127, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1646574', 'n_tokens_mistral': 2629, 'n_tokens_neox': 2586, 'n_words': 1036}