From 88d90eb892bc05dfeacd81937e788c4505fa68ef Mon Sep 17 00:00:00 2001 From: James McKinney <26463+jpmckinney@users.noreply.github.com> Date: Mon, 11 Nov 2024 15:33:25 -0500 Subject: [PATCH 1/6] fix: django.contrib.postgres.fields.JSONField causes an error in Django 4.2 (fields.E904) https://docs.djangoproject.com/en/4.2/ref/checks/ --- opencivicdata/core/models/base.py | 4 ++-- opencivicdata/legislative/models/bill.py | 8 ++++---- opencivicdata/legislative/models/event.py | 4 ++-- opencivicdata/legislative/models/vote.py | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/opencivicdata/core/models/base.py b/opencivicdata/core/models/base.py index 57a24a2..98799ee 100644 --- a/opencivicdata/core/models/base.py +++ b/opencivicdata/core/models/base.py @@ -2,7 +2,7 @@ import re import uuid from django.db import models -from django.contrib.postgres.fields import ArrayField, JSONField +from django.contrib.postgres.fields import ArrayField from django.core.validators import RegexValidator from ... import common @@ -53,7 +53,7 @@ class OCDBase(models.Model): auto_now=True, help_text="The last time this object was seen in a scrape." ) - extras = JSONField( + extras = models.JSONField( default=dict, blank=True, help_text="A key-value store for storing arbitrary information not covered elsewhere.", diff --git a/opencivicdata/legislative/models/bill.py b/opencivicdata/legislative/models/bill.py index 52a83be..f0cee7d 100644 --- a/opencivicdata/legislative/models/bill.py +++ b/opencivicdata/legislative/models/bill.py @@ -1,6 +1,6 @@ from __future__ import unicode_literals from django.db import models -from django.contrib.postgres.fields import ArrayField, JSONField +from django.contrib.postgres.fields import ArrayField from django.contrib.postgres.search import SearchVectorField from django.contrib.postgres.indexes import GinIndex @@ -101,7 +101,7 @@ class BillAction(RelatedBase): base_field=models.TextField(), blank=True, default=list ) # enum order = models.PositiveIntegerField() - extras = JSONField(default=dict, blank=True) + extras = models.JSONField(default=dict, blank=True) class Meta: db_table = "opencivicdata_billaction" @@ -170,7 +170,7 @@ class BillDocument(RelatedBase): bill = models.ForeignKey(Bill, related_name="documents", on_delete=models.CASCADE) note = models.CharField(max_length=300) date = models.CharField(max_length=10) # YYYY[-MM[-DD]] - extras = JSONField(default=dict, blank=True) + extras = models.JSONField(default=dict, blank=True) def __str__(self): return "{0} document of {1}".format(self.date, self.bill) @@ -183,7 +183,7 @@ class BillVersion(RelatedBase): bill = models.ForeignKey(Bill, related_name="versions", on_delete=models.CASCADE) note = models.CharField(max_length=300) date = models.CharField(max_length=10) # YYYY[-MM[-DD]] - extras = JSONField(default=dict, blank=True) + extras = models.JSONField(default=dict, blank=True) def __str__(self): return "{0} version of {1}".format(self.date, self.bill) diff --git a/opencivicdata/legislative/models/event.py b/opencivicdata/legislative/models/event.py index a3d98a4..d78ac44 100644 --- a/opencivicdata/legislative/models/event.py +++ b/opencivicdata/legislative/models/event.py @@ -1,5 +1,5 @@ from django.contrib.gis.db import models -from django.contrib.postgres.fields import ArrayField, JSONField +from django.contrib.postgres.fields import ArrayField from opencivicdata.core.models.base import ( OCDBase, LinkBase, @@ -161,7 +161,7 @@ class EventAgendaItem(RelatedBase): subjects = ArrayField(base_field=models.TextField(), blank=True, default=list) notes = ArrayField(base_field=models.TextField(), blank=True, default=list) event = models.ForeignKey(Event, related_name="agenda", on_delete=models.CASCADE) - extras = JSONField(default=dict, blank=True) + extras = models.JSONField(default=dict, blank=True) def __str__(self): return "Agenda item {0} for {1}".format(self.order, self.event).replace( diff --git a/opencivicdata/legislative/models/vote.py b/opencivicdata/legislative/models/vote.py index 76cf8dd..10b0a5f 100644 --- a/opencivicdata/legislative/models/vote.py +++ b/opencivicdata/legislative/models/vote.py @@ -1,5 +1,5 @@ from django.db import models -from django.contrib.postgres.fields import ArrayField, JSONField +from django.contrib.postgres.fields import ArrayField from opencivicdata.core.models.base import OCDBase, LinkBase, OCDIDField, RelatedBase from opencivicdata.core.models import Organization, Person @@ -48,7 +48,7 @@ class VoteEvent(OCDBase): on_delete=models.SET_NULL, ) - extras = JSONField(default=dict, blank=True) + extras = models.JSONField(default=dict, blank=True) def __str__(self): if self.identifier: From c09f37eba450df8a4c7955cfa18b47d4c5981504 Mon Sep 17 00:00:00 2001 From: James McKinney <26463+jpmckinney@users.noreply.github.com> Date: Mon, 11 Nov 2024 15:45:46 -0500 Subject: [PATCH 2/6] test: Make tests easier to run locally For example: env \ GEOS_LIBRARY_PATH='/opt/homebrew/opt/geos/lib/libgeos_c.dylib' \ GDAL_LIBRARY_PATH='/opt/homebrew/opt/gdal/lib/libgdal.dylib' \ DATABASE_DB=opencivicdata_test \ DATABASE_USER=myuser \ DATABASE_PASSWORD= \ PYTHONPATH=. pytest --ds=opencivicdata.tests.test_settings --- opencivicdata/tests/test_settings.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/opencivicdata/tests/test_settings.py b/opencivicdata/tests/test_settings.py index 5ade2f3..7b3768e 100644 --- a/opencivicdata/tests/test_settings.py +++ b/opencivicdata/tests/test_settings.py @@ -1,3 +1,5 @@ +import os + # not tests, just Django settings SECRET_KEY = "test" INSTALLED_APPS = ( @@ -8,10 +10,12 @@ DATABASES = { "default": { "ENGINE": "django.contrib.gis.db.backends.postgis", - "NAME": "test", - "USER": "test", - "PASSWORD": "test", + "NAME": os.getenv("POSTGRES_DB", "test"), + "USER": os.getenv("POSTGRES_USER", "test"), + "PASSWORD": os.getenv("POSTGRES_PASSWORD", "test"), "HOST": "localhost", } } MIDDLEWARE_CLASSES = () +GDAL_LIBRARY_PATH = os.getenv("GDAL_LIBRARY_PATH") +GEOS_LIBRARY_PATH = os.getenv('GEOS_LIBRARY_PATH') From 8d8cca2ab58472e87f46606bda0a51d1ab25043d Mon Sep 17 00:00:00 2001 From: James McKinney <26463+jpmckinney@users.noreply.github.com> Date: Mon, 11 Nov 2024 15:47:33 -0500 Subject: [PATCH 3/6] build: Upgrade minimum Django version to 3.2 --- .github/workflows/package.yml | 4 ++-- CHANGELOG.md | 2 ++ setup.py | 9 +++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 22e548d..9c098ad 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -27,8 +27,8 @@ jobs: - 5432:5432 strategy: matrix: - python-version: ['3.7', '3.8'] - django-series: ['2.2', '3.0'] + python-version: ['3.9', '3.10', '3.11', '3.12'] + django-series: ['3.2', '4.0', '4.2'] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} diff --git a/CHANGELOG.md b/CHANGELOG.md index e50e538..3b13d6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ ## Unreleased * Add a --sync flag to the loaddivisions management command, to delete divisions that are in the DB but not the CSV, even if the DB contains the CSV. This flag is relevant if you synchronize with a single CSV. +* Add support for Python 3.9, 3.10, 3.11, 3.12 and Django 4.0, 4.2. +* Drop support for Python 3.7, 3.8 and Django 2.2, 3.0. ## 3.3.0 (2023-05-08) diff --git a/setup.py b/setup.py index 2927b50..903d3e6 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ #!/usr/bin/env python from setuptools import setup, find_packages -install_requires = ["Django>=2.2", "psycopg2-binary"] +install_requires = ["Django>=3.2", "psycopg2-binary"] extras_require = { "dev": ["pytest>=3.6", "pytest-cov", "pytest-django", "coveralls==3.2.0", "flake8"] @@ -27,8 +27,9 @@ "License :: OSI Approved :: BSD License", "Natural Language :: English", "Operating System :: OS Independent", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", ], ) From 632448c3bccba0fdc443ba7e41add94e0178bda3 Mon Sep 17 00:00:00 2001 From: James McKinney <26463+jpmckinney@users.noreply.github.com> Date: Mon, 11 Nov 2024 15:51:33 -0500 Subject: [PATCH 4/6] build: Add migrations --- .../migrations/0009_auto_20241111_1450.py | 38 +++++++++++++++ .../migrations/0011_auto_20241111_1450.py | 43 +++++++++++++++++ .../migrations/0016_auto_20241111_1450.py | 48 +++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 opencivicdata/core/migrations/0009_auto_20241111_1450.py create mode 100644 opencivicdata/elections/migrations/0011_auto_20241111_1450.py create mode 100644 opencivicdata/legislative/migrations/0016_auto_20241111_1450.py diff --git a/opencivicdata/core/migrations/0009_auto_20241111_1450.py b/opencivicdata/core/migrations/0009_auto_20241111_1450.py new file mode 100644 index 0000000..94a590c --- /dev/null +++ b/opencivicdata/core/migrations/0009_auto_20241111_1450.py @@ -0,0 +1,38 @@ +# Generated by Django 3.2 on 2024-11-11 14:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0008_auto_20221215_1132'), + ] + + operations = [ + migrations.AlterField( + model_name='jurisdiction', + name='extras', + field=models.JSONField(blank=True, default=dict, help_text='A key-value store for storing arbitrary information not covered elsewhere.'), + ), + migrations.AlterField( + model_name='membership', + name='extras', + field=models.JSONField(blank=True, default=dict, help_text='A key-value store for storing arbitrary information not covered elsewhere.'), + ), + migrations.AlterField( + model_name='organization', + name='extras', + field=models.JSONField(blank=True, default=dict, help_text='A key-value store for storing arbitrary information not covered elsewhere.'), + ), + migrations.AlterField( + model_name='person', + name='extras', + field=models.JSONField(blank=True, default=dict, help_text='A key-value store for storing arbitrary information not covered elsewhere.'), + ), + migrations.AlterField( + model_name='post', + name='extras', + field=models.JSONField(blank=True, default=dict, help_text='A key-value store for storing arbitrary information not covered elsewhere.'), + ), + ] diff --git a/opencivicdata/elections/migrations/0011_auto_20241111_1450.py b/opencivicdata/elections/migrations/0011_auto_20241111_1450.py new file mode 100644 index 0000000..77ee7ee --- /dev/null +++ b/opencivicdata/elections/migrations/0011_auto_20241111_1450.py @@ -0,0 +1,43 @@ +# Generated by Django 3.2 on 2024-11-11 14:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('elections', '0010_auto_20221215_1132'), + ] + + operations = [ + migrations.AlterField( + model_name='ballotmeasurecontest', + name='extras', + field=models.JSONField(blank=True, default=dict, help_text='A key-value store for storing arbitrary information not covered elsewhere.'), + ), + migrations.AlterField( + model_name='candidacy', + name='extras', + field=models.JSONField(blank=True, default=dict, help_text='A key-value store for storing arbitrary information not covered elsewhere.'), + ), + migrations.AlterField( + model_name='candidatecontest', + name='extras', + field=models.JSONField(blank=True, default=dict, help_text='A key-value store for storing arbitrary information not covered elsewhere.'), + ), + migrations.AlterField( + model_name='election', + name='extras', + field=models.JSONField(blank=True, default=dict, help_text='A key-value store for storing arbitrary information not covered elsewhere.'), + ), + migrations.AlterField( + model_name='partycontest', + name='extras', + field=models.JSONField(blank=True, default=dict, help_text='A key-value store for storing arbitrary information not covered elsewhere.'), + ), + migrations.AlterField( + model_name='retentioncontest', + name='extras', + field=models.JSONField(blank=True, default=dict, help_text='A key-value store for storing arbitrary information not covered elsewhere.'), + ), + ] diff --git a/opencivicdata/legislative/migrations/0016_auto_20241111_1450.py b/opencivicdata/legislative/migrations/0016_auto_20241111_1450.py new file mode 100644 index 0000000..a348d6e --- /dev/null +++ b/opencivicdata/legislative/migrations/0016_auto_20241111_1450.py @@ -0,0 +1,48 @@ +# Generated by Django 3.2 on 2024-11-11 14:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('legislative', '0015_auto_20221215_1132'), + ] + + operations = [ + migrations.AlterField( + model_name='bill', + name='extras', + field=models.JSONField(blank=True, default=dict, help_text='A key-value store for storing arbitrary information not covered elsewhere.'), + ), + migrations.AlterField( + model_name='billaction', + name='extras', + field=models.JSONField(blank=True, default=dict), + ), + migrations.AlterField( + model_name='billdocument', + name='extras', + field=models.JSONField(blank=True, default=dict), + ), + migrations.AlterField( + model_name='billversion', + name='extras', + field=models.JSONField(blank=True, default=dict), + ), + migrations.AlterField( + model_name='event', + name='extras', + field=models.JSONField(blank=True, default=dict, help_text='A key-value store for storing arbitrary information not covered elsewhere.'), + ), + migrations.AlterField( + model_name='eventagendaitem', + name='extras', + field=models.JSONField(blank=True, default=dict), + ), + migrations.AlterField( + model_name='voteevent', + name='extras', + field=models.JSONField(blank=True, default=dict), + ), + ] From 48304e379b025ee27f1eae32d4ff819e2607f9eb Mon Sep 17 00:00:00 2001 From: James McKinney <26463+jpmckinney@users.noreply.github.com> Date: Mon, 11 Nov 2024 15:52:06 -0500 Subject: [PATCH 5/6] ci: Upgrade PostgreSQL version --- .github/workflows/package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 9c098ad..2485b58 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-20.04 services: postgres: - image: postgis/postgis:10-2.5 + image: postgis/postgis:12-2.5 env: POSTGRES_USER: test POSTGRES_DB: test From 80c189fe638dcf8375adaf9b5281e2f7417dbf44 Mon Sep 17 00:00:00 2001 From: James McKinney <26463+jpmckinney@users.noreply.github.com> Date: Mon, 11 Nov 2024 15:56:00 -0500 Subject: [PATCH 6/6] chore(flake8): Ignore migrations/ in all directories --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 3d351c8..a394494 100644 --- a/setup.cfg +++ b/setup.cfg @@ -2,4 +2,4 @@ universal = 1 [flake8] max-line-length=100 -exclude = opencivicdata/*/migrations +exclude = */migrations