Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync fork master branch #1

Merged
merged 32 commits into from
Mar 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
3e95ea7
Bump tox-gh-actions from 2.11.0 to 3.0.0 in /requirements
dependabot[bot] Dec 23, 2022
44f687e
Base manager can now be used for clean_duplicate_history
nick-traeger Jan 26, 2023
ad484d9
Bump black from 22.10.0 to 23.1.0 in /requirements (#1121)
dependabot[bot] Feb 4, 2023
cef0808
Bump isort from 5.10.1 to 5.12.0 in /requirements (#1118)
dependabot[bot] Feb 4, 2023
a836b88
Bump coverage from 6.5.0 to 7.1.0 in /requirements (#1114)
dependabot[bot] Feb 4, 2023
0a84855
Bump tox from 3.27.1 to 4.4.4 in /requirements
dependabot[bot] Feb 1, 2023
c6bd5c1
Merge pull request #1086 from jazzband/dependabot/pip/requirements/to…
ddabble Feb 4, 2023
697163d
[pre-commit.ci] pre-commit autoupdate (#1066)
pre-commit-ci[bot] Feb 4, 2023
2a28f2c
[pre-commit.ci] pre-commit autoupdate
pre-commit-ci[bot] Feb 6, 2023
add4f15
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 6, 2023
eca46b1
Merge pull request #1123 from jazzband/pre-commit-ci-update-config
ddabble Feb 6, 2023
0fcc722
Set USE_TZ explicitly to fix some failing tests
ddabble Feb 6, 2023
c971c14
Exclude testing py38+py39 with djmain
ddabble Feb 6, 2023
891174e
Corrected the test workflow badge URLs
ddabble Feb 6, 2023
636bcbc
Merge pull request #1115 from ideler/master
ddabble Feb 7, 2023
a95193a
Bump tox from 4.4.4 to 4.4.5 in /requirements
dependabot[bot] Feb 8, 2023
fdee87c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 8, 2023
79182d6
Merge pull request #1125 from jazzband/dependabot/pip/requirements/to…
ddabble Feb 8, 2023
018099c
Merge pull request #1124 from ddabble/fix/failing-tests
ddabble Feb 10, 2023
196ec68
Bump tox from 4.4.5 to 4.4.6 in /requirements
dependabot[bot] Feb 21, 2023
ce84402
Ensured lines don't exceed max length of 88
ddabble Feb 21, 2023
eeea6bf
Merge pull request #1130 from jazzband/dependabot/pip/requirements/to…
ddabble Feb 21, 2023
0c7abf8
Bump coverage from 7.1.0 to 7.2.0 in /requirements (#1134)
dependabot[bot] Feb 23, 2023
9e64b31
Bump coverage from 7.2.0 to 7.2.1 in /requirements (#1136)
dependabot[bot] Feb 27, 2023
a83fb5f
Prepared for release 3.3.0
ddabble Mar 8, 2023
6a849ce
Merge pull request #1139 from jazzband/prepare-3.3.0
ddabble Mar 8, 2023
e8cc2b2
Fixed tests in AdminSiteTest on Django main branch
ddabble Mar 8, 2023
17ad67c
Merge pull request #1140 from ddabble/fix/admin-tests-on-djmain
ddabble Mar 10, 2023
75daadf
[pre-commit.ci] pre-commit autoupdate (#1145)
pre-commit-ci[bot] Mar 14, 2023
5ab312d
Bump tox from 4.4.6 to 4.4.7 in /requirements (#1143)
dependabot[bot] Mar 14, 2023
3d0bf0c
Bump tox-gh-actions from 3.0.0 to 3.1.0 in /requirements (#1144)
dependabot[bot] Mar 14, 2023
321b783
Bump coverage from 7.2.1 to 7.2.2 in /requirements (#1148)
dependabot[bot] Mar 16, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ jobs:
- python-version: '3.7'
django-version: 'main'

- python-version: '3.8'
django-version: 'main'

- python-version: '3.9'
django-version: 'main'

- python-version: '3.11'
django-version: '3.2'
- python-version: '3.11'
Expand Down
10 changes: 5 additions & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
repos:
- repo: https://github.com/PyCQA/bandit
rev: 1.7.4
rev: 1.7.5
hooks:
- id: bandit
args:
- "-x *test*.py"

- repo: https://github.com/psf/black
rev: 22.10.0
rev: 23.1.0
hooks:
- id: black
language_version: python3.8
Expand All @@ -21,7 +21,7 @@ repos:
- "--config=tox.ini"

- repo: https://github.com/PyCQA/isort
rev: 5.10.1
rev: 5.12.0
hooks:
- id: isort

Expand All @@ -40,14 +40,14 @@ repos:
- id: detect-private-key

- repo: https://github.com/adrienverge/yamllint
rev: v1.28.0
rev: v1.29.0
hooks:
- id: yamllint
args:
- "--strict"

- repo: https://github.com/asottile/pyupgrade
rev: v3.2.2
rev: v3.3.1
hooks:
- id: pyupgrade
args: [--py37-plus]
19 changes: 16 additions & 3 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,27 @@ Changes
Unreleased
----------


3.3.0 (2023-03-08)
------------------

- Made it possible to use the new ``m2m_fields`` with model inheritance (gh-1042)
- Added two signals: ``pre_create_historical_m2m_records`` and ``post_create_historical_m2m_records`` (gh-1042)
- Added ``tracked_fields`` attribute to historical models (gh-1038)
- Fixed ``KeyError`` when running ``clean_duplicate_history`` on models with ``excluded_fields`` (gh-1038)
- Added support for Python 3.11 (gh-1053)
- Added Arabic translations (gh-1056)
- Fixed a code example under "Tracking many to many relationships" (gh-1069)
- Added a ``--base-manager`` option to the ``clean_duplicate_history`` management command (gh-1115)

3.2.0 (2022-09-28)
------------------

- Fixed typos in the docs
- Removed n+1 query from ``bulk_create_with_history`` utility (gh-975)
- Started using ``exists`` query instead of ``count`` in ``populate_history`` command (gh-982)
- Add basic support for many-to-many fields (gh-399)
- Added support for Django 4.1 (gh-1021)
- Added ``tracked_fields`` attribute to historical models (gh-1038)
- Fixed ``KeyError`` when running ``clean_duplicate_history`` on models with ``excluded_fields`` (gh-1038)
- Added support for Python 3.11 (gh-1053)

3.1.1 (2022-04-23)
------------------
Expand Down
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
django-simple-history
=====================

.. image:: https://github.com/jazzband/django-simple-history/workflows/build/badge.svg?branch=master
:target: https://github.com/jazzband/django-simple-history/actions?workflow=build
.. image:: https://github.com/jazzband/django-simple-history/actions/workflows/test.yml/badge.svg
:target: https://github.com/jazzband/django-simple-history/actions/workflows/test.yml
:alt: Build Status

.. image:: https://readthedocs.org/projects/django-simple-history/badge/?version=latest
Expand Down
8 changes: 8 additions & 0 deletions docs/utils.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ from the duplicate check

$ python manage.py clean_duplicate_history --auto --excluded_fields field1 field2

You can use Django's base manager to perform the cleanup over all records,
including those that would otherwise be filtered or modified by a
custom manager, by using the ``--base-manager`` flag.

.. code-block:: bash

$ python manage.py clean_duplicate_history --auto --base-manager

clean_old_history
-----------------------

Expand Down
2 changes: 1 addition & 1 deletion requirements/coverage.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
coverage==6.5.0
coverage==7.2.2
toml==0.10.2
4 changes: 2 additions & 2 deletions requirements/lint.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
black==22.10.0
black==23.1.0
flake8==6.0.0
isort==5.10.1
isort==5.12.0
4 changes: 2 additions & 2 deletions requirements/tox.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
-r ./coverage.txt
tox==3.27.1
tox-gh-actions==2.11.0
tox==4.4.7
tox-gh-actions==3.1.0
1 change: 1 addition & 0 deletions runtests.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ def __getitem__(self, item):
}
],
DEFAULT_AUTO_FIELD="django.db.models.AutoField",
USE_TZ=False,
)
MIDDLEWARE = [
"django.contrib.sessions.middleware.SessionMiddleware",
Expand Down
17 changes: 14 additions & 3 deletions simple_history/management/commands/clean_duplicate_history.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from django.db import transaction
from django.utils import timezone

from ... import models, utils
from ...exceptions import NotHistoricalModelError
from ... import utils
from . import populate_history


Expand Down Expand Up @@ -36,10 +35,19 @@ def add_arguments(self, parser):
nargs="+",
help="List of fields to be excluded from the diff_against check",
)
parser.add_argument(
"--base-manager",
action="store_true",
default=False,
help="Use Django's base manager to handle all records stored in the"
" database, including those that would otherwise be filtered or modified"
" by a custom manager.",
)

def handle(self, *args, **options):
self.verbosity = options["verbosity"]
self.excluded_fields = options.get("excluded_fields")
self.base_manager = options.get("base_manager")

to_process = set()
model_strings = options.get("models", []) or args
Expand Down Expand Up @@ -72,7 +80,10 @@ def _process(self, to_process, date_back=None, dry_run=True):
continue

# Break apart the query so we can add additional filtering
model_query = model.objects.all()
if self.base_manager:
model_query = model._base_manager.all()
else:
model_query = model._default_manager.all()

# If we're provided a stop date take the initial hit of getting the
# filtered records to iterate over
Expand Down
1 change: 0 additions & 1 deletion simple_history/management/commands/clean_old_history.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ def handle(self, *args, **options):
self._process(to_process, days_back=options["days"], dry_run=options["dry"])

def _process(self, to_process, days_back=None, dry_run=True):

start_date = timezone.now() - timezone.timedelta(days=days_back)
for model, history_model in to_process:
history_model_manager = history_model.objects
Expand Down
1 change: 0 additions & 1 deletion simple_history/management/commands/populate_history.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ def _bulk_history_create(self, model, batch_size):
# creating them. So we only keep batch_size worth of models in
# historical_instances and clear them after we hit batch_size
if index % batch_size == 0:

history.bulk_history_create(instances, batch_size=batch_size)

instances = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@


class Migration(migrations.Migration):

initial = True

dependencies = [migrations.swappable_dependency(settings.AUTH_USER_MODEL)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("migration_test_app", "0001_initial"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@


class Migration(migrations.Migration):

dependencies = [
(
"migration_test_app",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@


class Migration(migrations.Migration):

dependencies = [
(
"migration_test_app",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@


class Migration(migrations.Migration):

dependencies = [
(
"migration_test_app",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@


class Migration(migrations.Migration):

dependencies = [
(
"migration_test_app",
Expand Down
16 changes: 16 additions & 0 deletions simple_history/tests/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,22 @@ class PollWithAlternativeManager(models.Model):
history = HistoricalRecords()


class CustomPollManager(models.Manager):
def get_queryset(self):
return super().get_queryset().exclude(hidden=True)


class PollWithCustomManager(models.Model):
some_objects = CustomPollManager()
all_objects = models.Manager()

question = models.CharField(max_length=200)
pub_date = models.DateTimeField("date published")
hidden = models.BooleanField(default=False)

history = HistoricalRecords()


class IPAddressHistoricalModel(models.Model):
ip_address = models.GenericIPAddressField()

Expand Down
30 changes: 25 additions & 5 deletions simple_history/tests/tests/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,7 @@ def test_history_form_view_without_getting_history(self):
admin.history_form_view(request, poll.id, history.pk)

context = {
**admin_site.each_context(request),
# Verify this is set for original object
"original": poll,
"change_history": False,
Expand Down Expand Up @@ -484,7 +485,10 @@ def test_history_form_view_without_getting_history(self):
"save_on_top": admin.save_on_top,
"root_path": getattr(admin_site, "root_path", None),
}
context.update(admin_site.each_context(request))
# This key didn't exist prior to Django 4.2
if "log_entries" in context:
context["log_entries"] = ANY

mock_render.assert_called_once_with(
request, admin.object_history_form_template, context
)
Expand All @@ -509,6 +513,7 @@ def test_history_form_view_getting_history(self):
admin.history_form_view(request, poll.id, history.pk)

context = {
**admin_site.each_context(request),
# Verify this is set for history object not poll object
"original": history.instance,
"change_history": True,
Expand Down Expand Up @@ -538,7 +543,10 @@ def test_history_form_view_getting_history(self):
"save_on_top": admin.save_on_top,
"root_path": getattr(admin_site, "root_path", None),
}
context.update(admin_site.each_context(request))
# This key didn't exist prior to Django 4.2
if "log_entries" in context:
context["log_entries"] = ANY

mock_render.assert_called_once_with(
request, admin.object_history_form_template, context
)
Expand All @@ -563,6 +571,7 @@ def test_history_form_view_getting_history_with_setting_off(self):
admin.history_form_view(request, poll.id, history.pk)

context = {
**admin_site.each_context(request),
# Verify this is set for history object not poll object
"original": poll,
"change_history": False,
Expand Down Expand Up @@ -592,7 +601,10 @@ def test_history_form_view_getting_history_with_setting_off(self):
"save_on_top": admin.save_on_top,
"root_path": getattr(admin_site, "root_path", None),
}
context.update(admin_site.each_context(request))
# This key didn't exist prior to Django 4.2
if "log_entries" in context:
context["log_entries"] = ANY

mock_render.assert_called_once_with(
request, admin.object_history_form_template, context
)
Expand All @@ -617,6 +629,7 @@ def test_history_form_view_getting_history_abstract_external(self):
admin.history_form_view(request, obj.id, history.pk)

context = {
**admin_site.each_context(request),
# Verify this is set for history object
"original": history.instance,
"change_history": True,
Expand Down Expand Up @@ -648,7 +661,10 @@ def test_history_form_view_getting_history_abstract_external(self):
"save_on_top": admin.save_on_top,
"root_path": getattr(admin_site, "root_path", None),
}
context.update(admin_site.each_context(request))
# This key didn't exist prior to Django 4.2
if "log_entries" in context:
context["log_entries"] = ANY

mock_render.assert_called_once_with(
request, admin.object_history_form_template, context
)
Expand Down Expand Up @@ -676,6 +692,7 @@ def test_history_form_view_accepts_additional_context(self):
)

context = {
**admin_site.each_context(request),
# Verify this is set for original object
"anything_else": "will be merged into context",
"original": poll,
Expand Down Expand Up @@ -706,7 +723,10 @@ def test_history_form_view_accepts_additional_context(self):
"save_on_top": admin.save_on_top,
"root_path": getattr(admin_site, "root_path", None),
}
context.update(admin_site.each_context(request))
# This key didn't exist prior to Django 4.2
if "log_entries" in context:
context["log_entries"] = ANY

mock_render.assert_called_once_with(
request, admin.object_history_form_template, context
)
Expand Down
Loading