Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-django-avatar for
openSUSE:Factory checked in at 2026-01-22 15:18:30
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-django-avatar (Old)
and /work/SRC/openSUSE:Factory/.python-django-avatar.new.1928 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-django-avatar"
Thu Jan 22 15:18:30 2026 rev:16 rq:1328643 version:9.0.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-django-avatar/python-django-avatar.changes
2025-02-06 22:10:11.365895699 +0100
+++
/work/SRC/openSUSE:Factory/.python-django-avatar.new.1928/python-django-avatar.changes
2026-01-22 15:19:50.984407227 +0100
@@ -1,0 +2,9 @@
+Thu Jan 22 08:38:48 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 9.0.0:
+ * Fix files not closed in create_thumbnail
+ * Add Django 5.2 and 6.0 support
+ * Add Python 3.13, 3.14 support
+ * Drop Python 3.8, 3.9 support
+
+-------------------------------------------------------------------
Old:
----
django-avatar-8.0.1.tar.gz
New:
----
django-avatar-9.0.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-django-avatar.spec ++++++
--- /var/tmp/diff_new_pack.WuezNn/_old 2026-01-22 15:19:51.648434848 +0100
+++ /var/tmp/diff_new_pack.WuezNn/_new 2026-01-22 15:19:51.652435015 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-django-avatar
#
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
%{?sle15_python_module_pythons}
Name: python-django-avatar
-Version: 8.0.1
+Version: 9.0.0
Release: 0
Summary: Django-avatar package
License: BSD-3-Clause
++++++ django-avatar-8.0.1.tar.gz -> django-avatar-9.0.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-avatar-8.0.1/.github/workflows/release.yml
new/django-avatar-9.0.0/.github/workflows/release.yml
--- old/django-avatar-8.0.1/.github/workflows/release.yml 2024-09-05
04:07:29.000000000 +0200
+++ new/django-avatar-9.0.0/.github/workflows/release.yml 2026-01-07
22:07:17.000000000 +0100
@@ -11,12 +11,12 @@
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up Python
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v6
with:
python-version: 3.11
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-avatar-8.0.1/.github/workflows/test.yml
new/django-avatar-9.0.0/.github/workflows/test.yml
--- old/django-avatar-8.0.1/.github/workflows/test.yml 2024-09-05
04:07:29.000000000 +0200
+++ new/django-avatar-9.0.0/.github/workflows/test.yml 2026-01-07
22:07:17.000000000 +0100
@@ -5,32 +5,26 @@
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
- django-version: ['3.2', '4.1', '4.2', '5.0', '5.1.*']
+ python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
+ django-version: ['4.2', '5.2', '6.0.*']
exclude:
- - python-version: 3.11
- django-version: 3.2
-
- - python-version: 3.12
- django-version: 3.2
+ - python-version: 3.13
+ django-version: 4.2
- - python-version: 3.8
- django-version: 5.0
+ - python-version: 3.14
+ django-version: 4.2
- - python-version: 3.9
- django-version: 5.0
+ - python-version: 3.10
+ django-version: 6.0.*
- - python-version: 3.8
- django-version: 5.1.*
-
- - python-version: 3.9
- django-version: 5.1.*
+ - python-version: 3.11
+ django-version: 6.0.*
fail-fast: false
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v6
- name: 'Set up Python ${{ matrix.python-version }}'
- uses: actions/setup-python@v3
+ uses: actions/setup-python@v6
with:
python-version: '${{ matrix.python-version }}'
cache: 'pip'
@@ -48,4 +42,4 @@
coverage report
coverage xml
- name: Upload coverage reports to Codecov with GitHub Action
- uses: codecov/codecov-action@v3
+ uses: codecov/codecov-action@v5
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-avatar-8.0.1/.pre-commit-config.yaml
new/django-avatar-9.0.0/.pre-commit-config.yaml
--- old/django-avatar-8.0.1/.pre-commit-config.yaml 2024-09-05
04:07:29.000000000 +0200
+++ new/django-avatar-9.0.0/.pre-commit-config.yaml 2026-01-07
22:07:17.000000000 +0100
@@ -1,24 +1,24 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.6.0
+ rev: v6.0.0
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/pycqa/isort
- rev: "5.13.2"
+ rev: "7.0.0"
hooks:
- id: isort
args: ["--profile", "black"]
- repo: https://github.com/psf/black
- rev: 24.8.0
+ rev: 25.12.0
hooks:
- id: black
args: [--target-version=py310]
- repo: https://github.com/pycqa/flake8
- rev: '7.1.1'
+ rev: '7.3.0'
hooks:
- id: flake8
additional_dependencies:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-avatar-8.0.1/CHANGELOG.rst
new/django-avatar-9.0.0/CHANGELOG.rst
--- old/django-avatar-8.0.1/CHANGELOG.rst 2024-09-05 04:07:29.000000000
+0200
+++ new/django-avatar-9.0.0/CHANGELOG.rst 2026-01-07 22:07:17.000000000
+0100
@@ -1,5 +1,11 @@
Changelog
=========
+* 9.0.0
+ * Fix files not closed in `create_thumbnail`
+ * Add Django 5.2 and 6.0 support
+ * Add Python 3.13, 3.14 support
+ * Drop Python 3.8, 3.9 support
+
* 8.0.1
* Fix Django 5.1 compatibility
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-avatar-8.0.1/avatar/__init__.py
new/django-avatar-9.0.0/avatar/__init__.py
--- old/django-avatar-8.0.1/avatar/__init__.py 2024-09-05 04:07:29.000000000
+0200
+++ new/django-avatar-9.0.0/avatar/__init__.py 2026-01-07 22:07:17.000000000
+0100
@@ -1 +1 @@
-__version__ = "8.0.1"
+__version__ = "9.0.0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-avatar-8.0.1/avatar/models.py
new/django-avatar-9.0.0/avatar/models.py
--- old/django-avatar-8.0.1/avatar/models.py 2024-09-05 04:07:29.000000000
+0200
+++ new/django-avatar-9.0.0/avatar/models.py 2026-01-07 22:07:17.000000000
+0100
@@ -1,6 +1,7 @@
import binascii
import hashlib
import os
+from contextlib import closing
from io import BytesIO
from django.core.files import File
@@ -142,38 +143,38 @@
orig = self.avatar.storage.open(self.avatar.name, "rb")
except IOError:
return # What should we do here? Render a "sorry, didn't work"
img?
- try:
- image = Image.open(orig)
- image = self.transpose_image(image)
- quality = quality or settings.AVATAR_THUMB_QUALITY
- w, h = image.size
- if w != width or h != height:
- ratioReal = 1.0 * w / h
- ratioWant = 1.0 * width / height
- if ratioReal > ratioWant:
- diff = int((w - (h * ratioWant)) / 2)
- image = image.crop((diff, 0, w - diff, h))
- elif ratioReal < ratioWant:
- diff = int((h - (w / ratioWant)) / 2)
- image = image.crop((0, diff, w, h - diff))
- if settings.AVATAR_THUMB_FORMAT == "JPEG" and image.mode ==
"RGBA":
- image = image.convert("RGB")
- elif image.mode not in (settings.AVATAR_THUMB_MODES):
- image = image.convert(settings.AVATAR_THUMB_MODES[0])
- image = image.resize((width, height),
settings.AVATAR_RESIZE_METHOD)
- thumb = BytesIO()
- image.save(thumb, settings.AVATAR_THUMB_FORMAT,
quality=quality)
- thumb_file = ContentFile(thumb.getvalue())
- else:
+
+ with closing(orig):
+ try:
+ image = Image.open(orig)
+ except IOError:
thumb_file = File(orig)
+ else:
+ image = self.transpose_image(image)
+ quality = quality or settings.AVATAR_THUMB_QUALITY
+ w, h = image.size
+ if w != width or h != height:
+ ratioReal = 1.0 * w / h
+ ratioWant = 1.0 * width / height
+ if ratioReal > ratioWant:
+ diff = int((w - (h * ratioWant)) / 2)
+ image = image.crop((diff, 0, w - diff, h))
+ elif ratioReal < ratioWant:
+ diff = int((h - (w / ratioWant)) / 2)
+ image = image.crop((0, diff, w, h - diff))
+ if settings.AVATAR_THUMB_FORMAT == "JPEG" and image.mode
== "RGBA":
+ image = image.convert("RGB")
+ elif image.mode not in (settings.AVATAR_THUMB_MODES):
+ image = image.convert(settings.AVATAR_THUMB_MODES[0])
+ image = image.resize((width, height),
settings.AVATAR_RESIZE_METHOD)
+ thumb = BytesIO()
+ image.save(thumb, settings.AVATAR_THUMB_FORMAT,
quality=quality)
+ thumb_file = ContentFile(thumb.getvalue())
+ else:
+ thumb_file = File(orig)
thumb_name = self.avatar_name(width, height)
thumb = self.avatar.storage.save(thumb_name, thumb_file)
- except IOError:
- thumb_file = File(orig)
- thumb = self.avatar.storage.save(
- self.avatar_name(width, height), thumb_file
- )
- invalidate_cache(self.user, width, height)
+ invalidate_cache(self.user, width, height)
def avatar_url(self, width, height=None):
return self.avatar.storage.url(self.avatar_name(width, height))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-avatar-8.0.1/avatar/providers.py
new/django-avatar-9.0.0/avatar/providers.py
--- old/django-avatar-8.0.1/avatar/providers.py 2024-09-05 04:07:29.000000000
+0200
+++ new/django-avatar-9.0.0/avatar/providers.py 2026-01-07 22:07:17.000000000
+0100
@@ -68,7 +68,7 @@
class LibRAvatarProvider:
"""
- Returns the url of an avatar by the Ravatar service.
+ Returns the url of an avatar by the LibRavatar service.
"""
@classmethod
@@ -87,8 +87,17 @@
baseurl = "http://" + hostname + ":" + port + "/avatar/"
except Exception:
baseurl = "https://seccdn.libravatar.org/avatar/"
- hash = hashlib.md5(email.strip().lower()).hexdigest()
- return baseurl + hash
+
+ params = {"s": str(width)}
+ if settings.AVATAR_GRAVATAR_DEFAULT:
+ params["d"] = settings.AVATAR_GRAVATAR_DEFAULT
+ if settings.AVATAR_GRAVATAR_FORCEDEFAULT:
+ params["f"] = "y"
+ path = "%s/?%s" % (
+ hashlib.md5(force_bytes(email.strip().lower())).hexdigest(),
+ urlencode(params),
+ )
+ return urljoin(baseurl, path)
class FacebookAvatarProvider(object):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/django-avatar-8.0.1/avatar/templates/avatar/confirm_delete.html
new/django-avatar-9.0.0/avatar/templates/avatar/confirm_delete.html
--- old/django-avatar-8.0.1/avatar/templates/avatar/confirm_delete.html
2024-09-05 04:07:29.000000000 +0200
+++ new/django-avatar-9.0.0/avatar/templates/avatar/confirm_delete.html
2026-01-07 22:07:17.000000000 +0100
@@ -3,7 +3,7 @@
{% block content %}
{% if not avatars %}
- {% url 'avatar_change' as avatar_change_url %}
+ {% url 'avatar:change' as avatar_change_url %}
<p>{% blocktrans %}You have no avatars to delete. Please <a href="{{
avatar_change_url }}">upload one</a> now.{% endblocktrans %}</p>
{% else %}
<p>{% trans "Please select the avatars that you would like to delete."
%}</p>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-avatar-8.0.1/pyproject.toml
new/django-avatar-9.0.0/pyproject.toml
--- old/django-avatar-8.0.1/pyproject.toml 2024-09-05 04:07:29.000000000
+0200
+++ new/django-avatar-9.0.0/pyproject.toml 2026-01-07 22:07:17.000000000
+0100
@@ -13,20 +13,20 @@
classifiers=[
"Development Status :: 5 - Production/Stable",
"Environment :: Web Environment",
- "Framework :: Django",
"Intended Audience :: Developers",
"Framework :: Django",
- "Framework :: Django :: 3.2",
- "Framework :: Django :: 4.1",
"Framework :: Django :: 4.2",
+ "Framework :: Django :: 5.0",
+ "Framework :: Django :: 5.2",
+ "Framework :: Django :: 6.0",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: Python",
- "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",
+ "Programming Language :: Python :: 3.13",
+ "Programming Language :: Python :: 3.14",
]
dynamic = ["version", "dependencies"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-avatar-8.0.1/tests/tests.py
new/django-avatar-9.0.0/tests/tests.py
--- old/django-avatar-8.0.1/tests/tests.py 2024-09-05 04:07:29.000000000
+0200
+++ new/django-avatar-9.0.0/tests/tests.py 2026-01-07 22:07:17.000000000
+0100
@@ -1,7 +1,9 @@
import math
import os.path
+import sys
from pathlib import Path
from shutil import rmtree
+from unittest import skipIf
from django.contrib.admin.sites import AdminSite
from django.core import management
@@ -118,6 +120,7 @@
self.assertTrue(avatar.primary)
# We allow the .tiff file extension but not the mime type
+ @skipIf(sys.platform == "win32", "Skipping test on Windows platform")
@override_settings(AVATAR_ALLOWED_FILE_EXTS=(".png", ".gif", ".jpg",
".tiff"))
@override_settings(
AVATAR_ALLOWED_MIMETYPES=("image/png", "image/gif", "image/jpeg")
@@ -130,6 +133,7 @@
self.assertNotEqual(response.context["upload_avatar_form"].errors, {})
# We allow the .tiff file extension and the mime type
+ @skipIf(sys.platform == "win32", "Skipping test on Windows platform")
@override_settings(AVATAR_ALLOWED_FILE_EXTS=(".png", ".gif", ".jpg",
".tiff"))
@override_settings(
AVATAR_ALLOWED_MIMETYPES=("image/png", "image/gif", "image/jpeg",
"image/tiff")
@@ -141,6 +145,7 @@
self.assertEqual(len(response.redirect_chain), 1) # Redirect only if
it worked
self.assertEqual(response.context["upload_avatar_form"].errors, {})
+ @skipIf(sys.platform == "win32", "Skipping test on Windows platform")
@override_settings(AVATAR_ALLOWED_FILE_EXTS=(".jpg", ".png"))
def test_image_without_wrong_extension(self):
response = upload_helper(self, "imagefilewithoutext")
@@ -148,6 +153,7 @@
self.assertEqual(len(response.redirect_chain), 0) # Redirect only if
it worked
self.assertNotEqual(response.context["upload_avatar_form"].errors, {})
+ @skipIf(sys.platform == "win32", "Skipping test on Windows platform")
@override_settings(AVATAR_ALLOWED_FILE_EXTS=(".jpg", ".png"))
def test_image_with_wrong_extension(self):
response = upload_helper(self, "imagefilewithwrongext.ogg")